递归释放C结构

时间:2009-06-03 01:14:57

标签: c struct malloc

我有一个结构,只包含我已分配的内存指针。有没有办法以递归方式释放每个指针而不是在每个指针上自由调用?

例如,假设我有这样的布局:

typedef struct { ... } vertex;
typedef struct { ... } normal;
typedef struct { ... } texture_coord;

typedef struct
{
    vertex* vertices;
    normal* normals;
    texture_coord* uv_coords;
    int* quads;
    int* triangles;
} model;

在我的代码中,我将malloc的每个结构创建一个模型:

model* mdl = malloc (...);
mdl->vertices = malloc (...);
mdl->normals = malloc (...);
mdl->uv_coords = malloc (...);
mdl->quads = malloc (...);
mdl->triangles = malloc (...);

将每个指针释放为如此简单:

free (mdl->vertices);
free (mdl->normals);
free (mdl->uv_coords);
free (mdl->quads);
free (mdl->triangles);
free (mdl);

有没有办法可以递归迭代mdl中的指针而不是在每个元素上调用free?

在实践中,为每一个编写free()几乎没有任何工作,但它会减少代码重复并且对于学习非常有用)

8 个答案:

答案 0 :(得分:19)

不是真的 - 虽然你可以写一个方法来做所有六个自由,这样你就不会错过一个。

void freeModel( model* md1 ) {
    free (mdl->vertices);
    free (mdl->normals);
    free (mdl->uv_coords);
    free (mdl->quads);
    free (mdl->triangles);
    free (mdl);
}

答案 1 :(得分:7)

C语言中没有办法做到这一点,也不可取 - C不知道每个成员是通过malloc分配的不同指针,而C不包含运行时类型信息支持来执行此操作 - 在运行时,访问结构的编译代码只是为每个成员访问使用基指针的偏移量。

最简单的方法是编写“FreeModel”函数:

void FreeModel(model* mdl)
{
   free(mdl->vertices);
   ... // Other frees
   free(mdl);
}

答案 2 :(得分:7)

此类功能并非内置于C,但您可以通过滥用宏预处理器来作弊:

#define XX_MODEL_POINTERS do { \
  xx(vertices); xx(normals); xx(uv_coords); xx(quads); xx(triangles); \
} while(0)

分配:

model *mdl = malloc(sizeof(*mdl));
assert(mdl);
#define xx(N) mdl->N = malloc(sizeof(*mdl->N)); assert(mdl->N)
XX_MODEL_POINTERS;
#undef xx

免费:

assert(mdl);
#define xx(N) free(mdl->N); mdl->NULL
XX_MODEL_POINTERS;
#undef xx
free(mdl);
mdl = NULL;

令人讨厌的是,struct model的定义和XX_MODEL_POINTERS的定义可能会相互矛盾,而且无法捕捉它。出于这个原因,通过在某处解析.h文件来生成XX_MODEL_POINTERS的定义通常会更好。

C中的元编程绝非易事。

答案 3 :(得分:4)

如果您这样做,请查看talloc http://talloc.samba.org/

model* mdl = talloc (NULL, ...);
mdl->vertices = talloc (mdl, ...);
mdl->normals = talloc (mdl, ...);
mdl->uv_coords = talloc (mdl, ...);
mdl->quads = talloc (mdl, ...);
mdl->triangles = talloc (mdl, ...);

然后你可以:

talloc_free(mdl);

tallocfreetalloc作为第一个参数在分配时将mdl称为talloc(mdl->vertices, ...)的所有其他块(它将执行此操作)递归地你可以做talloc_free(mdl);而{{1}}也可以做到这一点

除此之外,使用talloc还有一些轻微的开销,因为它需要跟踪哪些内容递归,但它并不是很多。

答案 4 :(得分:3)

你可以一起计算所有这些所需的大小并做一个大的malloc

sizeof(model)+ sizeof(vertex)* nVertices ... etc。

将结果分配给mdl,将结果+ sizeof(模型)分配给model-> vertices ...

然后释放它只是一个免费。

您可能不得不担心对齐问题(取决于您的平台),但这不应该太难以理解。另一个问题是它是一个更大的块,如果在内存受限的环境中可能会出现问题。

答案 5 :(得分:2)

将所有免费内容扔进一个函数?

答案 6 :(得分:0)

不相信任何形式的C都可以。

您可以为该特定结构编写单独的函数,您可以在其中传递指针并将其释放。

编辑:太晚了,太晚了,从未见过那些答案......

答案 7 :(得分:0)

不是那些结构。您可以向顶级“模型”结构添加另一个条目,其中包含要释放的指针列表,并迭代该列表。但我怀疑该解决方案增加的复杂性和降低的可理解性是否值得。 (除非你在顶层'模型'结构中有更多更深入嵌套的条目,而不是你在这里展示的。)