6

我有一个结构,它只包含指向我分配的内存的指针。有没有办法递归地释放作为指针的每个元素,而不是在每个元素上调用 free?

例如,假设我有这个布局:

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

4

8 回答 8

20

不是真的——尽管你可以编写一个方法来完成所有六个释放,这样你就不会错过任何一个。

void freeModel( model* md1 ) {
    free (mdl->vertices);
    free (mdl->normals);
    free (mdl->uv_coords);
    free (mdl->quads);
    free (mdl->triangles);
    free (mdl);
}
于 2009-06-03T01:17:54.247 回答
8

此类功能未内置于 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可能会变得相互不一致,并且无法捕捉到它。出于这个原因,通常最好通过在XX_MODEL_POINTERS某处解析 .h 文件来生成 的定义。

C 中的元编程绝非易事。

于 2009-06-03T01:52:55.240 回答
7

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

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

void FreeModel(model* mdl)
{
   free(mdl->vertices);
   ... // Other frees
   free(mdl);
}
于 2009-06-03T01:20:48.783 回答
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);

and talloc will take care of free'ing all the other blocks you called talloc with mdl as the first argument at allocation time (and it will do this recursively you can do talloc(mdl->vertices, ...) and talloc_free(mdl); will get that too)

as an aside there is a slight overhead to using talloc because it needs to track what stuff recurse over, but it's not very much.

于 2010-06-17T20:26:49.003 回答
3

您可以一起计算所有这些所需的大小并执行一个大 malloc

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

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

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

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

于 2009-06-03T01:21:45.783 回答
2

把所有免费的都扔到一个函数中?

于 2009-06-03T01:18:27.523 回答
0

不相信这在任何形式的 C 中都是可能的。

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

编辑:起床,太晚了,从来没有看到那些答案......

于 2009-06-03T01:18:34.123 回答
0

不是那些结构。您可以将另一个条目添加到包含要释放的指针列表的顶级“模型”结构中,然后迭代该列表。但我怀疑该解决方案增加的复杂性和降低的可理解性是否值得。(除非您在顶级“模型”结构中释放的条目集比您在此处显示的要大得多且嵌套更深。)

于 2009-06-03T01:18:48.117 回答