73

假设我有这个结构

typedef struct person{
    char firstName[100], surName[51]
} PERSON;

我正在通过 malloc 分配空间并用一些值填充它

PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");

释放该结构占用的所有内存的正确且安全的方法是什么?是“免费的(testPerson);” 足够了还是我需要一个一个地释放每个结构的属性?

它引出了另一个问题——结构是如何存储在内存中的?我注意到一个奇怪的行为 - 当我尝试打印结构地址时,它等于它的第一个属性的地址。

printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);

这意味着这个 free(testPerson) 应该等于这个 free(testPerson->firstName);

这不是我想做的。

谢谢

4

7 回答 7

87

简单的回答:free(testPerson)就够了。

请记住,只有free()在使用或分配内存时才能使用。malloccallocrealloc

在您的情况下,您只有 malloced 内存,testPerson因此释放就足够了。

如果您在这种情况下使用char * firstname , *last surNamethen 来存储名称,则您必须分配内存,这就是您必须单独释放每个成员的原因。

这里还有一点应该是相反的;这意味着,为元素分配的内存稍后完成,因此free()它首先释放指向对象的指针。

释放每个元素,您可以看到如下所示的演示:

typedef struct Person
{
char * firstname , *last surName;
}Person;
Person *ptrobj =malloc(sizeof(Person)); // memory allocation for struct
ptrobj->firstname = malloc(n); // memory allocation for firstname
ptrobj->surName = malloc(m); // memory allocation for surName

.
. // do whatever you want

free(ptrobj->surName);
free(ptrobj->firstname);
free(ptrobj);

这背后的原因是,如果你释放第ptrobj一个,那么就会有内存泄漏,这是由指针分配firstname的内存。suName

于 2012-11-27T18:40:29.223 回答
7

首先您应该知道,在以下情况下定义和分配内存时分配了多少内存。

   typedef struct person{
       char firstName[100], surName[51]
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

1) sizeof(PERSON) 现在返回 151 个字节(不包括填充)

2)151字节的内存分配在堆中。

3)要免费,请致电免费(testPerson)。

但是如果您将结构声明为

  typedef struct person{
      char *firstName, *surName;
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

然后

1) sizeof(PERSON) 现在返回 8 个字节(不包括填充)

2) 需要通过调用 malloc() 或 calloc() 为 firstName 和 surName 分配内存。喜欢

        testPerson->firstName = (char *)malloc(100);

3)要释放,首先释放结构中的成员,而不是释放结构。即,免费(testPerson->firstName);免费(testPerson->surName);免费(测试人员);

于 2012-11-27T18:49:50.857 回答
5

因为您将 定义struct为由char数组组成,所以这两个字符串结构并且释放struct就足够了,也没有办法释放struct但保留数组。对于这种情况,您可能想做类似的事情struct { char *firstName, *lastName; },但是您需要分别为名称分配内存并处理何时释放内存的问题。

旁白:你有什么理由想在struct释放之后保留这些名字吗?

于 2012-11-27T18:41:10.787 回答
3

这样,您只需要释放结构,因为字段是具有静态大小的数组,将作为结构的一部分分配。这也是您看到的地址匹配的原因:数组是该结构中的第一件事。如果您将字段声明为 char *,您将不得不手动 malloc 并释放它们。

于 2012-11-27T18:42:32.497 回答
3

free还不够,free只是将内存标记为未使用,结构数据将在那里直到覆盖。为了安全起见,将指针设置为NULLafter free

前任:

if (testPerson) {
    free(testPerson);
    testPerson = NULL;
}

struct类似于数组,它是一块内存。您可以通过其偏移量访问结构成员。第一个结构的成员放置在偏移处,0因此第一个结构的成员的地址与结构的地址相同。

于 2016-03-02T04:30:43.867 回答
2

Mallocs 和 frees 需要配对。

malloc 为 Person 抓取了一块足够大的内存。

当您释放时,您告诉 malloc 不再需要从“这里”开始的那块内存,它知道它分配了多少并释放它。

无论你打电话

 free(testPerson) 

或者

 free(testPerson->firstName)

free() 实际接收到的只是一个地址,同一个地址,它不知道你调用的是哪个地址。如果您使用 free(testPerson),您的代码会更清晰 - 它显然与 malloc 匹配。

于 2012-11-27T18:41:22.480 回答
2

您不能释放未动态分配的类型。尽管数组在语法上相似(int* x = malloc(sizeof(int) * 4)可以以相同的方式使用int x[4]),但调用free(firstName)可能会导致后者出错。

例如,使用以下代码:

int x;
free(&x);

free()是一个接收指针的函数。&x是一个指针。这段代码可以编译,即使它根本不起作用。

如果我们假设所有内存都以相同的方式x分配,在定义处“分配”,在第二行“释放”,然后在作用域结束后再次“释放”。你不能两次释放同一个资源;它会给你一个错误。

这甚至没有提到由于某些原因,您可能无法在x不关闭程序的情况下释放内存。

tl;博士:只要释放struct你就会没事的。不要在数组上调用 free ;仅在动态分配的内存上调用它。

于 2012-11-27T18:42:52.600 回答