我有一个结构,只包含我已分配的内存指针。有没有办法以递归方式释放每个指针而不是在每个指针上自由调用?
例如,假设我有这样的布局:
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()几乎没有任何工作,但它会减少代码重复并且对于学习非常有用)
答案 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);
和talloc
将free
用talloc
作为第一个参数在分配时将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)
不是那些结构。您可以向顶级“模型”结构添加另一个条目,其中包含要释放的指针列表,并迭代该列表。但我怀疑该解决方案增加的复杂性和降低的可理解性是否值得。 (除非你在顶层'模型'结构中有更多更深入嵌套的条目,而不是你在这里展示的。)