You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含父指针的六叉树内存释放异常问题求助

解决六叉树内存释放问题

咱们先揪出你内存释放函数里的核心问题:你额外调用了delete leaf->prev;,这会直接导致重复释放父节点内存,甚至在父节点还没处理完所有子节点时就被提前删除,触发内存访问错误或者程序崩溃。

问题根源拆解

  • 每个节点的prev是指向父节点的引用,父节点的删除应该由它自己的递归调用负责。比如子节点执行delete leaf->prev时,父节点可能还在循环处理其他子节点,这会让父节点内存被提前释放,后续访问父节点的其他子节点就会碰到野指针问题。
  • 根节点的prev是NULL,delete NULL本身是安全的,但其他非根节点的prev都是有效父节点指针,重复删除同一内存地址会触发未定义行为。

修正后的内存释放函数

只需要删掉delete leaf->prev;这一行,让每个节点只负责自己的子节点删除,父节点的释放交给上层递归处理:

void destroy_tree(node *leaf) {
    if(leaf != NULL) {
        // 先递归遍历删除所有子节点
        for(int i=0; i<6; i++) {
            destroy_tree(leaf->p[i]);
        }
        // 最后删除当前节点
        delete leaf;
    }
}

额外优化建议

  1. 用构造函数简化节点初始化
    给node结构体加个构造函数,避免手动逐个赋值的繁琐,也减少初始化错误:
struct node {
    float value;
    int wins;
    int games;
    int visited;
    int colour;
    node *prev;
    node *p[6];

    // 构造函数自动初始化成员
    node(int col) : value(0.0), wins(0), games(0), visited(0), colour(col), prev(NULL) {
        memset(p, 0, sizeof(p)); // 把所有子节点指针置为NULL
    }
};

这样根节点初始化可以简化成:

node* root = new node(c); // c是根节点的颜色

扩展函数创建子节点也更简洁:

node *child = new node(leaf->colour == 1 ? -1 : 1);
child->prev = leaf;
leaf->p[column] = child;
  1. 用智能指针彻底告别手动内存管理(C++11+)
    如果你的项目支持C++11或更高版本,推荐用std::unique_ptr管理节点内存,完全不用写销毁函数,自动递归释放所有内存:
#include <memory>

struct node {
    float value = 0.0;
    int wins = 0;
    int games = 0;
    int visited = 0;
    int colour;
    node* prev = nullptr;
    std::unique_ptr<node> p[6] = {}; // 子节点用unique_ptr自动管理

    node(int col) : colour(col) {}
};

当根节点的unique_ptr被销毁时,会自动递归销毁所有子节点,彻底避免内存泄漏和重复释放问题。

内容的提问来源于stack exchange,提问作者John Meighan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:50:33