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
相关产品推荐
相关产品推荐

