我是否需要在结构中释放结构?

时间:2018-05-01 11:10:31

标签: c struct

我有以下代码。我想妥善释放我的所有记忆。如您所见,我在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);
}

3 个答案:

答案 0 :(得分:8)

  

我想知道是否需要在a_struct中手动释放b_struct

没有

来自malloc(3)手册页:

  

free()函数释放ptr指向的内存空间,该内存空间必须由之前调用malloc()calloc()或{{1}返回}。

分配realloc()字节时,包括该结构的所有成员,包括sizeof(struct a_struct)成员。此结构成员与struct b_structint成员没有区别;它只是分配器的一个连续内存块。

答案 1 :(得分:2)

没有。您不仅需要,而且不允许b中使用的内存是a中使用的内存的一部分;你需要将后者作为一个单元释放,并且包括b的所有内存。

一般情况下,对于freemalloc的每次通话,您的计划都应拨打calloc一次。这并不意味着调用free的代码行数需要与调用分配函数的行数相同;这意味着每次运行程序时,对free的每次调用都应与对分配函数的一次调用配对,反之亦然,但有限的例外情况除外:

  • 如果分配失败(并返回NULL),则无需在free上致电NULL
  • 您可以根据需要多次拨打free NULL,尽管您通常不需要。
  • 您可以调用库函数,然后在内部分配或释放内存。这不是一个例外;这些功能中的每一个仍然必须与相应的免费或分配(分别)相匹配,但如果您只是查看malloccallocfree,您可能会遗漏某些内容。
  • 如果您最早有机会在程序退出之前释放大块内存,那么您无需费心,因为操作系统无论如何都要回收所有内存。这一点尤其有其自己的注意事项,但它们最多与此问题相关。

如果未能分配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;
}

您应该只从freemalloccalloc返回realloc指针值。