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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:09:27