【问题标题】:C - freeing structsC - 释放结构
【发布时间】:2012-11-15 11:05:49
【问题描述】:

假设我有这个结构

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);

这意味着 免费(测试人) 应该等于这个 免费(testPerson->firstName);

这不是我想做的。

谢谢

【问题讨论】:

  • 一个好的经验法则:对于每个 malloc,您都需要一个免费的(不多也不少)。

标签: c struct malloc


【解决方案1】:

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

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

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

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

这里还有一点应该是倒序;这意味着,为元素分配的内存稍后完成,所以 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,那么就会有内存泄漏,即firstnamesuName指针分配的内存。

【讨论】:

  • 对于最后一句,内存泄漏可能是由于结构填充。
  • No.. 我说如果free(ptrobj) 完成,那么firstnamesuname 指针是堆上的成员,它已经消失了,所以firstname 和@987654337 分配的内存@ 不会被释放,因为要释放它,你必须写 free(firstname) 但名字不再存在 ..hopw 你明白了
【解决方案2】:

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

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

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

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

3) 要释放,请调用 free(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) 要释放,首先释放结构中的成员,而不是释放结构。 IE, 免费(testPerson->firstName); 免费(testPerson->surName); 免费(testPerson);

【讨论】:

  • 谢谢。所以我只需要处理动态变量,就像函数中一样
【解决方案3】:

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

旁白:在struct 被释放后,您是否有原因想要保留这些名称?

【讨论】:

  • 我不想保留任何东西,就是这样 :) 释放它(使用 free(testPerson))后,我仍然能够通过 testPerson->surName 访问它的 surName 并返回正确的值,但我无法访问它的第一个属性(firstName),它给了我一些随机字符。这就是为什么我担心 free(testPerson) 是否足够
  • 嗯,我现在明白了,我只是担心其他结构属性被卡在内存中。谢谢
  • @user10099 free 仅更改alloc 系列函数用于记账的内存部分中的一些数据,这意味着组成字符串的字符将保留在内存中,直到它们被覆盖,但是您调用了 free (1) 再次访问该内存在形式上是不正确的(除非以后的分配重用它)并且 (2) 您无法保证那里有什么。
  • @user10099 内存仍然存在的原因是因为它还没有被操作系统清理。您仍然可以访问该信息的原因是因为这个原因,所以实际上如果在调用 free 后访问一部分内存,则称为“未定义行为”
  • @dierre 谢谢,8 年后内存不知何故自己清理了
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    free 还不够,free 只是将内存标记为未使用,结构数据将一直存在直到覆盖。为安全起见,请在free 之后将指针设置为NULL

    例如:

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

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

    【讨论】:

      【解决方案6】:

      mallocs 和 frees 需要配对。

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

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

      不管你打电话

       free(testPerson) 
      

       free(testPerson->firstName)
      

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

      【讨论】:

      • 我认为free(testPerson->firstName) 让初学者感到困惑,关于它的工作原理。
      • 正如我所说的清晰代码将使用免费(testPerson)。但是,无法避免另一个调用实际上会起作用的事实,这就是内存模型的工作方式。有时你必须理解指针。
      【解决方案7】:

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

      以这段代码为例:

      int x;
      free(&x);
      

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

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

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

      tl;dr:只要释放 struct 就可以了。 不要在数组上调用free;只在动态分配的内存上调用它。

      【讨论】:

      • 另外,变量通常不在堆上分配,这就是free(&x) 可能已经失败的原因。
      • 我很想对语言的粗心使用投反对票,但不会阻止新用户发帖。但是,有两个明显的错误需要指出:不清楚“数组由指针表示”是什么意思,也不清楚“有效代码”是什么意思。诠释 x;免费(&x);不是有效的代码。
      • @MK.:感谢您指出这些错误;我试图弄清楚如何正确表达它,因为我想确保我没有使用适用于 C++ 而不是 C 的语言。现在更清楚了。
      猜你喜欢
      • 2010-09-30
      • 2021-07-30
      • 1970-01-01
      • 2012-07-20
      • 2011-07-25
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 2015-12-20
      相关资源
      最近更新 更多