我有以下代码。我想妥善释放我的所有记忆。如您所见,我在a_struct中有一个b_struct。我想知道是否需要在a_struct中手动释放b_struct,如果是,那么正确的方法是什么?
#include <stdlib.h>
#include <stdio.h>
struct b_struct {
int c;
};
struct a_struct {
struct b_struct b;
};
int main(int argc, char **argv)
{
struct a_struct *a;
a = calloc(1, sizeof(*a));
a->b.c = 5;
printf("Value: %d", a->b.c);
free(a);
}
答案 0 :(得分:8)
我想知道是否需要在a_struct中手动释放b_struct
没有
来自malloc(3)
手册页:
free()
函数释放ptr
指向的内存空间,该内存空间必须由之前调用malloc()
,calloc()
或{{1}返回}。
分配realloc()
字节时,包括该结构的所有成员,包括sizeof(struct a_struct)
成员。此结构成员与struct b_struct
或int
成员没有区别;它只是分配器的一个连续内存块。
答案 1 :(得分:2)
没有。您不仅需要,而且不允许。 b
中使用的内存是a
中使用的内存的一部分;你需要将后者作为一个单元释放,并且包括b
的所有内存。
一般情况下,对于free
或malloc
的每次通话,您的计划都应拨打calloc
一次。这并不意味着调用free
的代码行数需要与调用分配函数的行数相同;这意味着每次运行程序时,对free
的每次调用都应与对分配函数的一次调用配对,反之亦然,但有限的例外情况除外:
NULL
),则无需在free
上致电NULL
。free
NULL
,尽管您通常不需要。malloc
,calloc
和free
,您可能会遗漏某些内容。如果未能分配free
内存,则会出现内存泄漏。你的程序将使用越来越多的内存,直到操作系统无法再提供它为止,此时它可能会崩溃。
如果free
内存未被其中一个标准分配函数分配,或者free
内存两次相同,那就更糟了:这是立即未定义的行为(UB)并且可能会什么*。这是您尝试释放b
时会引入的错误类型;有问题的内存不是calloc
返回的实际指针,即使它已经作为a
的一部分被释放了。
*人们常说UB可能会做很多事情,但实际上你可以预测真实系统会发生什么。它不会让您的计算机爆炸,除非您实际上有USB炸弹插入有问题的计算机。但是,我会将无效的frees归类为UB的一种较不稳定的类型:它引入的错误在实践中可能比实际的bug出现得晚,导致看似无关的问题,并且在程序的多次运行之间不稳定(意味着事情可能会发生)测试时看起来很好但是当你尝试使用该程序时失败,并且很难调试。对于许多其他形式的UB,这是允许的,但在实践中不太可能发生。
答案 2 :(得分:1)
在这种情况下,没有。
如果内部结构与外部结构分开分配,则只需手动释放内部结构。例如:
struct a_struct
{
struct b_struct *b;
};
int main( void )
{
struct a_struct *a = malloc( sizeof *a );
if ( a ) // *Always* check the result of malloc or calloc
{
a->b = malloc( sizeof *a->b );
if ( a->b )
{
// do stuff with a->b->c
free( a->b ); // free in reverse order that you allocated
}
free( a );
}
return 0;
}
您应该只从free
,malloc
或calloc
返回realloc
指针值。