VS Code中C++二叉树代码触发Segmentation Fault,疑与析构器相关
C++二叉树代码段错误问题分析与修复
问题现象
在Visual Code中运行以下二叉树代码时,chooseNextPosition方法的if (value >= current->getValue())行触发Segmentation Fault段错误。尝试将析构函数逻辑替换为普通方法调用时代码可正常运行,且代码在Visual Studio中通过g++编译运行无异常。
完整代码
#include <iostream> class Node { private: int value; Node* right; Node* left; Node* prev; public: Node(int value) : value{ value }, right{ nullptr }, left{ nullptr }, prev{ nullptr } {} Node(const Node& node) : value{ node.value }, right{ nullptr }, left{ nullptr }, prev{ nullptr } {} void setValue(const int& new_value) { this->value = new_value; } void setRight(Node* new_right) { this->right = new_right; this->right->prev = this; } void setLeft(Node* new_left) { this->left = new_left; this->left->prev = this; } const int& getValue() const { return this->value; } Node* getRight() { return this->right; }; Node* getLeft() { return this->left; } Node* getPrev() { return this->prev; }; friend std::ostream& operator<<(std::ostream& os, const Node& node); ~Node() { if (this->right != nullptr) delete this->right; if (this->left != nullptr) delete this->left; value = 0; } }; std::ostream& operator<<(std::ostream& os, const Node& node) { return os << node.getValue(); } class Tree { private: Node* root; Node* chooseNextPosition(Node* current, int value) const { if (current == nullptr) return nullptr; //TODO throw exception if (value >= current->getValue()) { current = current->getRight(); } else { current = current->getLeft(); } return current; } public: Tree() = default; Node* getRoot() { return this->root; } void insert(int value) { if (this->root == nullptr) { this->root = new Node(value); return; } Node* current{ nullptr }; Node* next_current{ this->root }; while (next_current != nullptr) { current = next_current; next_current = chooseNextPosition(current, value); } if (value >= current->getValue()) { current->setRight(new Node(value)); } else { current->setLeft(new Node(value)); } } const Node* getNext(Node* current) const // ? { if (current == nullptr) return nullptr; //TODO throw exception return(current->getLeft()); } Node* find(int value, Node* root) //this->root = root; { Node* current{ root }; if (root == nullptr) { std::cout << "element doesn`t exist" << std::endl; return nullptr; } if (current->getValue() == value) return current; current = chooseNextPosition(current, value); find(value, current); } void printTree(Node* root) //root = this->root { if (root != nullptr) { printTree(root->getLeft()); std::cout << root->getValue() << " "; printTree(root->getRight()); } } void dl() { if (root != nullptr) delete(this->root); } ~Tree() { if (root != nullptr) delete(this->root); } }; int main() { Tree tree; tree.insert(45); tree.insert(55); tree.insert(34); tree.insert(1); tree.insert(28); tree.printTree(tree.getRoot()); std::cout << std::endl; Node* tmp = tree.find(1, tree.getRoot()); std::cout << tree.find(1, tree.getRoot())->getPrev()->getValue() << std::endl; }
问题根源
段错误的直接原因并非析构函数,而是**find函数未返回递归调用的结果**:
在find函数中,递归调用find(value, current)时没有将结果返回,导致函数执行到末尾会返回一个未定义的垃圾指针(野指针)。后续代码中对这个野指针调用getPrev()时,会访问非法内存,触发Segmentation Fault。
修复方案
1. 修正find函数的返回逻辑
修改find函数,确保递归调用的结果被返回:
Node* find(int value, Node* root) { Node* current{ root }; if (root == nullptr) { std::cout << "element doesn`t exist" << std::endl; return nullptr; } if (current->getValue() == value) return current; current = chooseNextPosition(current, value); return find(value, current); // 新增return,返回递归结果 }
2. 修复Tree类默认构造函数的未初始化问题
默认构造函数Tree() = default;不会自动将指针成员root初始化为nullptr,可能导致未定义行为,需显式初始化:
Tree() : root(nullptr) {}
3. 增加空指针检查避免潜在崩溃
在main函数中,对find的返回值做空指针检查,防止后续调用崩溃:
int main() { Tree tree; tree.insert(45); tree.insert(55); tree.insert(34); tree.insert(1); tree.insert(28); tree.printTree(tree.getRoot()); std::cout << std::endl; Node* found = tree.find(1, tree.getRoot()); if (found != nullptr && found->getPrev() != nullptr) { std::cout << found->getPrev()->getValue() << std::endl; } else { std::cout << "节点或其父节点不存在" << std::endl; } }
内容的提问来源于stack exchange,提问作者Nikita Developer
相关产品推荐
相关产品推荐

