递归释放C结构
我有一个结构,只包含指向我分配的内存的指针。有没有一种方法可以递归释放每个指针的元素,而不是每个元素都*调用?递归释放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);
有没有一种方法,我可以递归迭代通过MDDL指针比在每个元素上*调用?
(在实践中它几乎没有任何工作,只是写的free()为每一个,但它会减少代码的重复和学习是有用的)
这样的功能并不内置于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
的定义和的定义可能会变得相互矛盾,并且无法捕捉它。由于这个原因,通常通过解析某个地方的.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);
}
把所有的免费的功能?
我不相信,在任何形式下
你可以为特定的结构,你会通过指针并释放他们那里编写一个单独的功能是可能的。
编辑:UPS,为时已晚,没有看到这些问题的答案...
不能与那些结构。您可以向包含要释放的指针列表的*“模型”结构添加其他条目,并迭代该列表。但我怀疑该解决方案的复杂性和可理解性是否值得。 (除非你在顶层“模型”结构中有很多更大和更深层嵌套的条目集,而不是你在这里展示的)。
C语言没有办法做到这一点,也不是所希望的 - C不知道每个成员是通过malloc分配的不同的指针,而C不包含运行时类型的信息支持来执行此操作 - 在运行时,访问该结构的编译代码只是使用偏移关闭每个成员访问的基指针。
最简单的方法是写一个“FreeModel”功能:
void FreeModel(model* mdl)
{
free(mdl->vertices);
... // Other frees
free(mdl);
}
,你可以计算出所需要的所有的人都在一起的大小和做一个大的malloc
的sizeof(模型)+的sizeof (顶点)* nVertices ...等
分配结果MDL,结果+的sizeof(模型)到模型 - >顶点......
然后释放它仅仅是一个FRE即
您可能不得不担心对齐问题(取决于您的平台),但这不应该太难以弄清楚。另一个问题是它是一个更大的块,如果在内存受限的环境中可能会出现问题。
看看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
照顾“荷兰国际集团所有你mdl
称为talloc
其他块作为分配时的第一个参数(并且它将递归执行此操作,您可以执行talloc(mdl->vertices, ...)
和talloc_free(mdl);
也可以)
作为一边使用talloc有一个小的开销,因为它需要跟踪什么东西递归,但它不是很多。
啊聪明,谢谢!虽然这个解决方案确实看起来很脏,但是它避免了代码重复而没有性能损失,这是我以前从未见过的方法。我可能不会在实践中使用它,但它会用一个有趣的实现来解决我的问题,而不仅仅是重新组织代码。 – Kai 2009-06-03 02:06:29