c - 在具有相同类型成员的结构上使用 free

标签 c recursion struct free stack-overflow

我是一个学习C的菜鸟,我一直在尝试增强Simple Object System .

我有一个如下所示的结构:

struct Room
{
    Object proto;
    Monster* bad_guy;
    struct Room *north;
    struct Room *south;
    struct Room *east;
    struct Room *west;
};

我想释放这个:

void Room_destroy(void* self)
{
    Room* room=self;
    if(room->bad_guy)
        room->bad_guy->proto.destroy(room->bad_guy);
    if(room->north)
        room->north.proto.destroy(room->north);//same as Room_destroy
    if(room->south)
        room->north.proto.destroy(room->south);////same as Room_destroy
    if(room->west)
        room->north.proto.destroy(room->west);////same as Room_destroy
    if(room->east)
        room->north.proto.destroy(room->east);////same as Room_destroy
    free(room->proto.description);
    free(room);
}

假设有两个房间,Room* x 和 Room* y,这样 x 位于 y,调用该方法x 将调用 y 上的方法,该方法将在 x 上调用该方法,而 x 将在 y 上调用该方法,然后返回如此反复会导致死锁。我该如何解决这个问题?

如何释放此类内存以确保不会发生内存泄漏?

编辑:

我尝试实现一组函数来调用它,但我同时遇到了 StackOverflowSegmentation failure:

    ==6446== Stack overflow in thread 1: can't grow stack to 0xffe801ff8
    ==6446== 
    ==6446== Process terminating with default action of signal 11 (SIGSEGV)
    ==6446==  Access not within mapped region at address 0xFFE801FF8
    ==6446==    at 0x400863: Room_destroy (ex19.c:55)
    ==6446==  If you believe this happened as a result of a stack
    ==6446==  overflow in your program's main thread (unlikely but
    ==6446==  possible), you can try to increase the size of the
    ==6446==  main thread stack using the --main-stacksize= flag.
    ==6446==  The main thread stack size used in this run was 8388608.
    ==6446== Stack overflow in thread 1: can't grow stack to 0xffe801fe8
    ==6446== 
    ==6446== Process terminating with default action of signal 11 (SIGSEGV)
    ==6446==  Access not within mapped region at address 0xFFE801FE8
    ==6446==    at 0x4A256A0: _vgnU_freeres (vg_preloaded.c:58)
    ==6446==  If you believe this happened as a result of a stack
    ==6446==  overflow in your program's main thread (unlikely but
    ==6446==  possible), you can try to increase the size of the
    ==6446==  main thread stack using the --main-stacksize= flag.
    ==6446==  The main thread stack size used in this run was 8388608.
    ==6446== 
    ==6446== HEAP SUMMARY:
    ==6446==     in use at exit: 605 bytes in 12 blocks
    ==6446==   total heap usage: 12 allocs, 0 frees, 605 bytes allocated
    ==6446== 
    ==6446== LEAK SUMMARY:
    ==6446==    definitely lost: 0 bytes in 0 blocks
    ==6446==    indirectly lost: 0 bytes in 0 blocks
    ==6446==      possibly lost: 0 bytes in 0 blocks
    ==6446==    still reachable: 605 bytes in 12 blocks
    ==6446==         suppressed: 0 bytes in 0 blocks
    ==6446== Reachable blocks (those to which a pointer was found) are not shown.
    ==6446== To see them, rerun with: --leak-check=full --show-leak-kinds=all
    ==6446== 
    ==6446== For counts of detected and suppressed errors, rerun with: -v
    ==6446== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    Segmentation fault

这是我的代码:

  void Room_destroy(void* self)

{ 房间*房间=自己; if(房间->坏人) 房间->bad_guy->proto.destroy(房间->bad_guy);

    if(room->north && !avoid(caller,room->north))
        room->north->proto.destroy(room->north);
    else
        caller=room->north;

if(room->south &&!avoid(caller,room->south))
    room->south->proto.destroy(room->south);
else
    caller=room->south;

if(room->west && !avoid(caller,room->west))
    room->west->proto.destroy(room->west);
else
    caller=room->west;

if(room->east && !avoid(caller,room->east))
    room->east->proto.destroy(room->east);
else
    caller=room->east;

free(room->proto.description);
//room->proto=NULL;
free(room);

}

避免方法在这里:

  int avoid(Room* caller,Room* room)
{
if(caller!=room)
    return 0;
return 1;
 }

然后有一个 Map 结构,如下所示:

  struct Map
 {
Object proto;
Room *start;
Room* location;
 };

在这个结构上,我像这样调用了 destroy 方法:

  void Map_destroy(void* self)
{
Map *map=self;
if(map->start)
{
    caller=map->start;
    map->start->proto.destroy(map->start);
}
if(map->location)
{
    caller=map->location;   
    map->location->proto.destroy(map->location);
}   

}

当用户像这样中止程序时调用此函数:

 case -1:
    printf("Giving up? You suck\n");
    if(game)
        game->proto.destroy(game);
    return 0;

最佳答案

假设在某个时刻,您使用了 addRoom 方法将您的房间添加到房间网络中。然后,您应该有一个方法 removeRoom 来执行相反的操作。

所以如果你的房子\建筑物\房间图处于状态S0,那么

S0-(add room x)-> S1 -(remove room x)-> S2.

S0 必须等于 S2。所以你可以使用

removeRoom(network, x)
freeRoom(x);

要一次性删除所有内容,请使用

while(isEmpty(network) ){
   x = getHead(network)
   removeRoom(network, x)
  freeRoom(x);    
}

与C中的链表原理相同

关于c - 在具有相同类型成员的结构上使用 free,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20563659/

相关文章:

php - 使用递归构建动态 super 菜单?

c++ - 如何在 C++ 中连接两个结构类型变量?

c - 在 C 中使用结构并返回二维数组

c - 在 C 编程中使用数组、循环和条件

c - c 中的 "assignment makes integer from pointer without a cast "警告

php - 查找 child 部门的员工 - PHP

java - 为什么不能将 LinkedList 的最后一个节点设置为 null?

c - 为什么这个 print 语句可以阻止 C 程序崩溃?

c - 在 C 中正常 block (#155) 后检测到堆损坏

c - 赋值类型不兼容