假设我有一个结构:
typedef struct{
char *ID;
char *name;
float price;
int quantity;
} Generic_Properties;
现在,如果我使用 malloc 为它分配堆中的空间并将地址保存在指针中,让我们称他为 p1
. 现在我想释放那个特定的内存块,只需声明free(p1)
就足够了吗:
free(p1);
还是我需要单独释放 ID 和名称指针,因为我使用 malloc 为它们指向的字符串分配空间?
规则是,malloc
和free
应该成对出现。释放所有只malloc
一次的东西。
char name[] = "some_name";
Generic_Properties *p1 = malloc(...); /* 1 */
p1->ID = malloc(...); /* 2 */
p1->name = name;
...
...
/* free(p1->name); Don't do this, p1->name was not allocated with malloc*/
free(p1->ID); /* 2' */
free(p1); /* 1' */
/* if(p1 && p1->name[0] == '?') {} don't dereference p1 after it is freed. It is dangling now */
...
...
/* free(p1); don't free p1 again as it is already freed and is dangling. */
p1 = NULL;
free(p1); /* OK */
还是我需要单独释放 ID 和名称指针,因为我使用 malloc 为他们指向的字符串分配空间?
正如Mohit Jain所指出的,每次调用malloc
后都必须有一个free
呼叫,但在这种情况下(见下面的评论),没有什么能阻止您在一次调用中为所有内容保留空间:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
char *ID;
char *name;
float price;
int quantity;
} Generic_Properties;
int main(void)
{
Generic_Properties *x = malloc(sizeof(*x) + 100);
x->ID = (char *)(x + 1);
x->name = x->ID + 50;
strcpy(x->ID, "00001");
strcpy(x->name, "David");
printf("%s %sn", x->ID, x->name);
free(x);
return 0;
}
处理这种结构的一种更面向对象的方法是定义用于分配和释放此类结构的函数。
(此代码的改进版本)
// Allocate a GP object
Generic_Properties * create_GP()
{
Generic_Properties * p;
p = malloc(sizeof(Generic_Properties));
memset(p, 0, sizeof(*p));
return p;
}
// Deallocate a GP object
void free_GP(Generic_Properties *p)
{
if (p == NULL)
return;
free(p->ID);
p->ID = NULL;
free(p->name);
p->name = NULL;
free(p);
}
补遗
如果你想将这种方法与@Alter曼恩的方法结合起来,你可以做这样的事情:
// Allocate a GP object
Generic_Properties * create_GP2(const char *id, const char *name)
{
size_t idLen;
size_t nameLen;
Generic_Properties * p;
// Reserve space for GP, GP.ID, and GP.name
// all in one malloc'd block
idLen = strlen(id) + 1;
nameLen = strlen(name) + 1;
p = malloc(sizeof(Generic_Properties) + idLen + nameLen);
memset(p, 0, sizeof(*p));
// Save the ID
p->ID = (char *)p + sizeof(Generic_Properties);
memcpy(p->ID, id, idLen);
// Save the name
p->name = p->ID + idLen;
memcpy(p->name, name, nameLen);
return p;
}
// Deallocate a GP object
void free_GP2(Generic_Properties *p)
{
free(p);
}