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

C++二叉树打印时节点被垃圾值替换,触发段错误求助

嘿,别担心,这其实是C++里超容易踩的经典坑——悬空指针问题!我来帮你把问题拆解得明明白白~

首先直接点出核心问题:你在make_tree函数里创建的c1和c2是局部栈变量,当当前递归调用的栈帧结束后,这些变量占用的内存会被系统回收。但你却把它们的地址&c1、&c2传给了新创建的Cell对象,后续调用disp递归访问这些指针时,指向的已经是无效内存了——这就是为什么你会看到随机垃圾值,甚至触发段错误。

具体看代码里的问题点

在make_tree这段代码里:

Cell c1 = *(cells.end() - 1);
cells.pop_back();
Cell c2 = *(cells.end() - 1);
cells.pop_back();
Cell cell = Cell(c1.getScore() + c2.getScore(), &c1, &c2);

c1和c2是从vector里拷贝出来的临时局部变量,一旦当前递归调用完成,它们的内存就会被释放。而新创建的cell里的next_r和next_l还死死指着这些已经失效的内存地址,后续访问自然会出问题。

另外还有个小细节:main里你用new Cell(i)创建对象后拷贝到vector,但没释放ptr,会造成内存泄漏——不过这不是当前崩溃的直接原因,但也是需要修正的点。

修复方案(推荐现代C++的智能指针用法)

最稳妥的方式是用智能指针管理对象生命周期,避免手动操作原始指针踩坑。这里用std::unique_ptr来实现,它会自动帮你管理内存,杜绝悬空指针和内存泄漏:

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

class Cell{
    int score;
    unique_ptr<Cell> next_l;
    unique_ptr<Cell> next_r;
public:
    Cell(int s = 0, unique_ptr<Cell> r = nullptr, unique_ptr<Cell> l = nullptr)
        : score(s), next_r(move(r)), next_l(move(l)) {}

    int getScore(){
        return score;
    }

    void disp(){
        cout << "Score: " << score << endl;
        if(next_r != nullptr){
            next_r->disp();
        }
        if(next_l != nullptr){
            next_l->disp();
        }
    }
};

unique_ptr<Cell> make_tree(vector<unique_ptr<Cell>> &cells){
    if(cells.size() == 1){
        return move(cells[0]);
    }else{
        auto c1 = move(cells.back());
        cells.pop_back();
        auto c2 = move(cells.back());
        cells.pop_back();
        auto cell = make_unique<Cell>(c1->getScore() + c2->getScore(), move(c1), move(c2));
        cells.push_back(move(cell));
        return make_tree(cells);
    }
}

int main(){
    vector<unique_ptr<Cell>> cells;
    for(int i = 0; i < 3; i++){
        cells.push_back(make_unique<Cell>(i));
    }
    auto head = make_tree(cells);
    head->disp();
    return 0;
}

修复逻辑说明

  • 用std::unique_ptr<Cell>替代原始指针,它会自动在对象不再被使用时释放内存,彻底避免悬空指针问题。
  • 用move语义转移智能指针的所有权,既避免了不必要的对象拷贝,又保证每个Cell对象只有一个所有者。
  • 不再手动调用new和delete,把内存管理的工作交给标准库,减少出错概率。

毕竟好几年没碰C了,踩这个坑真的很正常——现代C的内存管理已经比早年友好太多啦,慢慢捡起来就好~

内容的提问来源于stack exchange,提问作者Adam Jijo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:30:09