如何释放链接结构的结构

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 是什么。

编辑: 我注意到这段代码有一个隐含的假设。 它假设由房间构建的图形具有树结构。如果图形是完全连接的网格或有任何循环,则此代码将不起作用,并导致内存问题,例如双重释放和无效访问。

但我正在研究任何图形的解决方案