C -释放结构

bgibtngc  于 2023-03-07  发布在  其他
关注(0)|答案(8)|浏览(122)

假设我有一个结构体

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

我用malloc分配空间并用一些值填充它

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

释放该结构体占用的所有内存的正确而安全的方法是什么?is“free(testPerson);“足够了,还是需要逐个释放每个结构体的属性?
这就引出了另一个问题--结构是如何存储在内存中的?我注意到一个奇怪的现象--当我试图打印结构地址时,它等于它的第一个属性的地址。

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

这意味着这个free(testPerson)应该等于这个free(testPerson-〉firstName);
这不是我想做的。
谢谢

9cbw7uwe

9cbw7uwe1#

答案很简单:free(testPerson)就足够了。
请记住,只有在使用malloccallocrealloc分配内存时,才可以使用free()
在您的示例中,只有testPerson的错位内存,因此释放这些内存就足够了。
如果你使用了char * firstname , *last surName,那么在这种情况下,为了存储name,你必须分配内存,这就是为什么你必须单独释放每个成员。
这里也有一点它应该以相反的顺序;这意味着,为元素分配的内存是稍后完成的,因此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指针分配的内存。

jtjikinw

jtjikinw2#

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

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

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

sh7euo9m

sh7euo9m3#

首先你应该知道,当你定义和分配内存时,有多少内存被分配。

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)要释放,先释放结构体中的成员,然后再释放结构体。例如,free(testPerson-〉firstName);free(测试人-〉姓氏);自由(测试人员);

aoyhnmkz

aoyhnmkz4#

因为我们定义了structchar数组组成,所以两个字符串 * 是 * 结构,释放struct就足够了,也没有办法释放struct而保留数组。在这种情况下,我们需要做类似struct { char *firstName, *lastName; }的事情。但随后您需要分别为名称分配内存,并处理何时释放内存的问题。
旁白:在struct被释放后,您是否有 * 原因 * 要保留这些名称?

zdwk9cvp

zdwk9cvp5#

这样你只需要释放结构,因为字段是静态大小的数组,将作为结构的一部分分配。这也是你看到的地址匹配的原因:数组是这个结构中的第一个元素。2如果你把字段声明为char *,你就必须手动分配并释放它们。

lp0sw83n

lp0sw83n6#

雄鹿和自由兽需要配对。
malloc抓取了一块足够Person使用的内存。
当你释放内存的时候,你告诉malloc从“这里”开始的那块内存不再需要了,它知道它分配了多少内存,然后释放它。
无论你打电话

free(testPerson)

free(testPerson->firstName)

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

hs1ihplo

hs1ihplo7#

不能释放非动态分配的类型。虽然数组在语法上相似(int* x = malloc(sizeof(int) * 4)可以和int x[4]一样使用),但是调用free(firstName)可能会导致后者出错。
例如,使用以下代码:

int x;
free(&x);

free()是一个接受指针的函数。&x是一个指针。这段代码可以编译,即使它根本不工作。
如果我们假设所有的内存都是以相同的方式分配的,那么x在定义处被“分配”,在第二行被“释放”,然后在作用域结束后再次被“释放”。它会给予你一个错误。
这甚至没有提到这样一个事实,即由于某些原因,您可能无法在不关闭程序的情况下释放x的内存。
tl;dr:只要释放struct就可以了。* 不要 * 在数组上调用free;只能在动态分配的内存上调用它。

p5cysglq

p5cysglq8#

以后的AKA转世问题

在你的例子中,我会额外地将你的变量的整个内存分配设置为零。否则,新的内存分配可能会包含你释放的示例的数据。最后,也将变量设置为NULL,在某些情况下,我遇到了麻烦,没有这样做。

void 
our_person_dispose(PERSON **p)   // pass your person as pointer to finally reset the actual variable to NULL
{
  if (!*p) return;               // check if p is not NULL for safety reasons
  memset(*p, 0, sizeof(PERSON)); // set allocated memory to 0
  free(*p);                      // free dereferenced pointer to variable
  *p = NULL;                     // set variable to NULL to avoid some bughunts later on
}

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

our_person_dispose(&anon_alc);   // stay clean for good

此致

相关问题