递归释放C结构

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

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

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()几乎没有任何工作,但它会减少代码重复并且对于学习有用

这样的function不是内置于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中的元编程绝非易事。

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

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

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

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

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

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

sizeof(model)+ sizeof(vertex)* nVertices …等

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

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

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

如果您这样做,请查看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); 

talloc将负责free所有其他你称为talloc块, talloc mdl作为分配时的第一个参数(并且它将以递归方式执行此操作,你可以执行talloc(mdl->vertices, ...)talloc_free(mdl);也会得到这个)

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

把所有免费的东西扔进一个函数?

认为任何forms的C都不可能。

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

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

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