如何释放链接结构的结构
How to free a structure of linked structures
我有这个结构
struct room {
char* name;
char* description;
struct room *north;
struct room *south;
struct room *east;
struct room *west;
struct container* items;
};
所以我应该写一个函数
struct room* destroy_room(struct room* room);
释放用于创建房间的所有内存和 return NULL 作为新房间参考。
所以我认为简单地做
free(room);
return NULL;
可以解决问题,但没有。
正如 Jabberwocky 所说,"nothing is freed automatically",因此您的函数可能如下所示:
void destroy_room(struct room* room)
{
if (!room) return;
if (room->name) free(room->name);
if (room->description) free(room->description);
if (room!=room->north) destroy_room(room->north);
if (room!=room->south) destroy_room(room->south);
if (room!=room->east) destroy_room(room->east);
if (room!=room->west) destroy_room(room->west);
free_items(room->items);
free(room);
}
我会选择使用两个独立函数的解决方案。第一个是 destroy_room
它将释放一个房间并从其邻居中删除对自身的引用:
struct room* destroy_room(struct room* room) {
if (!room) return;
if (room->name) free(room->name);
if (room->description) free(room->description);
if (room->items) free_items(room->items);
// remove the references to this room from its neighbors
if (room->north) room->north->south = NULL;
if (room->south) room->south->north = NULL;
if (room->east) room->east->west = NULL;
if (room->west) room->west->east = NULL;
free(room);
return NULL;
}
然后可以使用此函数编写递归函数,以释放从给定房间可到达的所有房间。该函数保存对邻居的引用,然后释放给定的房间,然后递归地释放邻居:
struct room* destroy_rooms_rec(struct room* room)
{
if (!room) return;
// save references to neighbors
struct room* north = room->north;
struct room* south = room->south;
struct room* east = room->east;
struct room* west = room->west;
// free this room
destroy_room(room);
// free all neighbors
destroy_rooms_rec(north);
destroy_rooms_rec(south);
destroy_rooms_rec(east);
destroy_rooms_rec(west);
return NULL;
}
注意:我假设像 free_items(struct container* items)
这样的函数存在,可以释放任何 items
是什么。
编辑: 我注意到这段代码有一个隐含的假设。
它假设由房间构建的图形具有树结构。如果图形是完全连接的网格或有任何循环,则此代码将不起作用,并导致内存问题,例如双重释放和无效访问。
但我正在研究任何图形的解决方案
我有这个结构
struct room {
char* name;
char* description;
struct room *north;
struct room *south;
struct room *east;
struct room *west;
struct container* items;
};
所以我应该写一个函数
struct room* destroy_room(struct room* room);
释放用于创建房间的所有内存和 return NULL 作为新房间参考。
所以我认为简单地做
free(room);
return NULL;
可以解决问题,但没有。
正如 Jabberwocky 所说,"nothing is freed automatically",因此您的函数可能如下所示:
void destroy_room(struct room* room)
{
if (!room) return;
if (room->name) free(room->name);
if (room->description) free(room->description);
if (room!=room->north) destroy_room(room->north);
if (room!=room->south) destroy_room(room->south);
if (room!=room->east) destroy_room(room->east);
if (room!=room->west) destroy_room(room->west);
free_items(room->items);
free(room);
}
我会选择使用两个独立函数的解决方案。第一个是 destroy_room
它将释放一个房间并从其邻居中删除对自身的引用:
struct room* destroy_room(struct room* room) {
if (!room) return;
if (room->name) free(room->name);
if (room->description) free(room->description);
if (room->items) free_items(room->items);
// remove the references to this room from its neighbors
if (room->north) room->north->south = NULL;
if (room->south) room->south->north = NULL;
if (room->east) room->east->west = NULL;
if (room->west) room->west->east = NULL;
free(room);
return NULL;
}
然后可以使用此函数编写递归函数,以释放从给定房间可到达的所有房间。该函数保存对邻居的引用,然后释放给定的房间,然后递归地释放邻居:
struct room* destroy_rooms_rec(struct room* room)
{
if (!room) return;
// save references to neighbors
struct room* north = room->north;
struct room* south = room->south;
struct room* east = room->east;
struct room* west = room->west;
// free this room
destroy_room(room);
// free all neighbors
destroy_rooms_rec(north);
destroy_rooms_rec(south);
destroy_rooms_rec(east);
destroy_rooms_rec(west);
return NULL;
}
注意:我假设像 free_items(struct container* items)
这样的函数存在,可以释放任何 items
是什么。
编辑: 我注意到这段代码有一个隐含的假设。 它假设由房间构建的图形具有树结构。如果图形是完全连接的网格或有任何循环,则此代码将不起作用,并导致内存问题,例如双重释放和无效访问。
但我正在研究任何图形的解决方案