2009-06-03 121 views
3

我有一个结构,只包含指向我分配的内存的指针。有没有一种方法可以递归释放每个指针的元素,而不是每个元素都自由调用?递归释放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()为每一个,但它会减少代码的重复和学习是有用的)

回答

6

这样的功能并不内置于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中进行元编程是不容易的。

+1

啊聪明,谢谢!虽然这个解决方案确实看起来很脏,但是它避免了代码重复而没有性能损失,这是我以前从未见过的方法。我可能不会在实践中使用它,但它会用一个有趣的实现来解决我的问题,而不仅仅是重新组织代码。 – Kai 2009-06-03 02:06:29

18

不是真的 - 虽然你可以写一个方法全部六次解脱,这样你就不会错过任何一次。

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

把所有的免费的功能?

0

不相信,在任何形式下

你可以为特定的结构,你会通过指针并释放他们那里编写一个单独的功能是可能的。

编辑:UPS,为时已晚,没有看到这些问题的答案...

0

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

7

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

最简单的方法是写一个“FreeModel”功能:

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

,你可以计算出所需要的所有的人都在一起的大小和做一个大的malloc

的sizeof(模型)+的sizeof (顶点)* nVertices ...等

分配结果MDL,结果+的sizeof(模型)到模型 - >顶点......

然后释放它仅仅是一个FRE即

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

3

看看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有一个小的开销,因为它需要跟踪什么东西递归,但它不是很多。