【问题标题】:Read access violation on destroying a binary search tree破坏二叉搜索树时的读取访问冲突
【发布时间】:2018-06-01 23:09:00
【问题描述】:

晚上好。 尝试销毁我的 BST 时出现访问冲突异常错误。 之前有过关于这个的帖子,我复制了他们接受的答案的回复,但仍然没有得到预期的结果。 所以我有这个二叉搜索树实现。一切正常,直到我的代码从我的 int main() 函数到达“return 0”。

我会为你留下一些代码。

PQBST::~PQBST()
{
    destroy();
}

inline void PQBST::destroy()
{
    if (root)
        destroy(root);
}

void PQBST::destroy(Node* node)
{
    if (node->left) // this is where it gives me and access violation exception 0xDDDDDDDD
        destroy(node->left);
    if (node->right)
        destroy(node->right);
    delete node;
}

我知道当你尝试删除已经被释放的东西时会抛出这种错误,但我不明白为什么当我在我的应用程序(当我完成它时)。 我评论了我手动销毁我的 BST 的部分,在达到“返回 0”后,它又给了我

Unhandled exception thrown: read access violation.
node was 0xFF12C6AB

所以它不是 0xDDDDDDDD 但仍然是一个错误。 :|

我的节点如下所示:

struct Node
{
    Human info;
    Node * left;
    Node * right;
    Node() {};
    Node(Human value)
        : info(value), left(NULL), right(NULL)
    {

    }
};

我的 BST 类只有 Node* root 。 我希望我给了你足够的信息。 谢谢。

编辑:我的节点现在看起来像这样:

    struct Node
{
    Human info;
    Node * left;
    Node * right;
    Node() { left = NULL, right = NULL;  }
    Node(Human value): info(value), left(NULL), right(NULL){}
    Node(Human value, Node* left, Node* right) : info(value), left(left), right(right) {}
    Node& operator=(const Node& n)
    {
        info = n.info;
        left = n.left;
        right = n.right;

        return *this;
    }

    Human getInfo() const { return info; }
    Node* getLeft() { return left; }
    Node* getRight() { return right;  }
    ~Node() { };
};

我的 PQBST:

class PQBST
{
private:
    Node * root;
    int m; //spaceship size - given by the user

public:
    PQBST() { root = NULL; }
    PQBST(int m) : root(NULL), m(m) {}
    PQBST(Node* root, int m);
    ~PQBST();

PQBST::PQBST(Node * root, int m)
{
    this->root = root;
    this->m = m;
}

【问题讨论】:

  • 在取消引用和访问成员之前,void PQBST::destroy(Node* node) 中的任何内容都不会检查非NULL
  • Node() {}; 使 leftright 未初始化。厄运的可能性很大。
  • 根据the big list of magic numbers at Wikipedia,0xDDDDDDDD 是已经被释放的内存。确保您已正确实施the Rule of Three
  • 打开的错误可能性太多。投票结束。建议使用minimal reproducible example 缩小问题范围。
  • 好的,我会试着查一下你说的。谢谢! *抱歉没有一个足够简单的例子,我不知道还要添加什么。

标签: c++ binary-search-tree access-violation


【解决方案1】:

如果你要删除你的 BST,我建议你做一个post order traversal。这将递归地访问左、右然后删除节点。如果树的构造正确,这将起作用。

void PQBST::destroy(Node* node)
{
    if (!node) return;
    destroy(node->left);
    destroy(node->right);
    delete node;
}

话虽如此,我建议不要尝试手动管理内存并使用std::unique_ptr<T>,其中T 是您的节点类型。我会在您的 BST 中将它们定义为std::unique_ptr<Node> left, right;。这完全避免了这个问题。

【讨论】:

  • if(!node) return 确实是缺少的。在某些时候,OP 正在发布一个没有有效root 的 PQBST。好电话。
  • 所以,我尝试了你们所说的一切。我还调试了 return 0 并且显然它通过了所有“~PQBST”方法(我不知道为什么)并且它在 :inline void PQBST::destroy() { if (root) destroy(root); 处崩溃。 } 。由于我的根不是 NULL(但包含一些垃圾内容),它会继续运行并命中另一个垃圾节点->left。
  • 我会完全放弃管理内存并使用 unique_ptr。
  • 不幸的是,这是一个结构和数据算法类项目(在 BST 上实现的优先级队列),我不允许使用会让生活更轻松的东西......
  • @BryukiHK 现在在你的~PQBST() 你不需要delete(root) 你只需要调用函数destroy(root); 就可以了。
【解决方案2】:

我知道当你尝试删除已经被释放的东西时会抛出这种错误,但我不明白为什么当我调用destroy函数时它会尝试破坏我的BST两次一次在我的应用程序中(当我完成后)

不确定我是否正确解释了您上面所说的内容(粗体),但您不是已经在PQBST::~PQBST() 中调用了PQBST::destroy() 吗?如果你也手动调用PQBST::destroy(),在调用析构函数的时候会不会被调用两次?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多