首页 > 解决方案 > 为什么我的 bool 函数返回 true 会导致读取访问冲突?

问题描述

我目前正在使用 unique_ptr 编写 BST。我有布尔函数(删除)来删除数据,然后调用递归函数(removeNode,它返回一个布尔值)来查找节点并将其删除。但是,有时当 remove 函数返回 true 时,它​​会在内存库中引发读取访问冲突。我不太了解 return 在函数中的工作原理,无法完全理解正在发生的事情。此问题与返回布尔值无关。当函数试图返回调用该函数的“this”对象时,就会发生访问冲突。

我已经建立了断点并且递归函数返回就好了。它返回真。我已将发生此错误的行全部大写,因为我无法弄清楚如何突出显示它。

这是调用递归函数的删除函数

virtual bool removeNode(const T& data)
{
   if (root == nullptr) return false;
   if (data < root->data)
   {
    return removeNode(root->lhChild, root, false, data);
   }
   else if (data > root->data)
   {
    return removeNode(root->rhChild, root, true, data);
   }
   else if (data == root->data)
   {
    if (isLeaf(root))
    {
       root.reset(nullptr);
       --szTree;
       return true;
    }
    else if ((root->lhChild != nullptr) && (root->rhChild != nullptr))
    {
       std::unique_ptr<Node<T>> temp(root->lhChild.get());
       while (temp->rhChild != nullptr)
       {
          temp.reset(temp->rhChild.get());
       }
       root->data = temp->data;
       bool rtn = removeNode(root->lhChild, root, false, temp->data);
       RETURN TRUE;
    }
    else if (root->lhChild != nullptr)
    {
       root->data = root->lhChild->data;
       return removeNode(root->lhChild, root, false, root->data);
    }
    else
    {
       root->data = root->rhChild->data;
       return removeNode(root->rhChild, root, false, root->data);
    }
   }
}

这是递归函数:

bool removeNode(std::unique_ptr<Node<T>>& n, std::unique_ptr<Node<T>>& p, bool isRh, T data)
{
   if (n == nullptr) return false;
   else if (n->data == data)
   {
    if (isLeaf(n))
    {
       n.reset(nullptr);
       if (isRh) p->rhChild.reset(nullptr);
       else p->lhChild.reset(nullptr);
       --szTree;
       return true;
    }
    else if ((n->lhChild != nullptr) && (n->rhChild != nullptr))
    {
       std::unique_ptr<Node<T>> temp(n->lhChild.get());
       while (temp->rhChild != nullptr)
       {
        temp.reset(temp->rhChild.get());
       }
       n->data = temp->data;
       return removeNode(n->lhChild, n, false, temp->data);
    }
    else if (n->lhChild != nullptr)
    {
       p->lhChild = std::move(n->lhChild);
       --szTree;
       return true;
    }
    else
    {
       p->rhChild = std::move(n->rhChild);
       --szTree;
       return true;
    }
   }
   else if (data < n->data) return removeNode(n->lhChild, n, false, data);
   else return removeNode(n->rhChild, n, true, data);
}

如果它有帮助,那就是内存中发生错误的地方

_NODISCARD pointer get() const noexcept { // return pointer to object
        return this->_Myptr();
    }

错误内容如下:

Exception thrown: read access violation.
std::_Unique_ptr_base<Node<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::default_delete<Node<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >::_Myptr(...) returned 0xDDDDDDFD. occurred

它应该像正常一样返回 true,但由于某种原因,它无法返回调用该函数的对象。由于我对函数返回时发生的事情的了解有限,我什至不知道如何解决这个问题。

标签: c++memorybinary-search-treeunique-ptraccess-violation

解决方案


这是因为其中一个unique_ptrs 的析构函数导致访问冲突。

这是因为您不止一次地删除了一个对象。当 unique_ptr 被销毁时,它也会删除它指向的对象。此外,调用resetunique_ptr 会删除它之前指向的对象。

所以当你这样做时

while (temp->rhChild != nullptr)
{
    temp.reset(temp->rhChild.get());
}

实际上,在查看它们之后,您正在删除所有仍在树中的节点。而且,树中的 unique_ptr(大概)仍然指向那些已删除的节点。所以你有悬空指针的问题。


推荐阅读