为什么我的 bool 函数返回 true 会导致读取访问冲突?
Why does my bool function returning true result in read access violation?
我目前正在使用 unique_ptr 编写 BST。我有布尔函数(删除)来删除数据,然后调用递归函数(removeNode,return 是一个布尔值)来查找节点并将其删除。然而,有时当 remove 函数为 returning true 时,它会在内存库中引发读取访问冲突。我不太了解 return 如何在函数中工作以完全理解正在发生的事情。此问题与 returning 布尔无关。当该函数随后尝试 return 调用该函数的 "this" 对象时,发生了访问冲突。
我已经建立了断点,递归函数return很好。 return 是真的。我将发生此错误的行全部大写,因为我不知道如何突出显示它。
这里是调用递归函数的remove函数
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
它应该 return 正常,但由于某种原因它在 return 调用该函数的对象时遇到问题。由于我对函数 returns 时发生的事情的了解有限,我什至不知道如何解决这个问题。
这是因为 unique_ptr
之一的析构函数导致访问冲突。
这是因为您多次删除一个对象。当 unique_ptr 被销毁时,它也会删除它指向的对象。此外,在 unique_ptr 上调用 reset
会删除它之前指向的对象。
所以当你这样做时
while (temp->rhChild != nullptr)
{
temp.reset(temp->rhChild.get());
}
你实际上是在删除所有这些仍在树中的节点,在你查看它们之后。而且,树中的 unique_ptr (大概)仍然指向那些已删除的节点。所以你有悬挂指针的问题。
我目前正在使用 unique_ptr 编写 BST。我有布尔函数(删除)来删除数据,然后调用递归函数(removeNode,return 是一个布尔值)来查找节点并将其删除。然而,有时当 remove 函数为 returning true 时,它会在内存库中引发读取访问冲突。我不太了解 return 如何在函数中工作以完全理解正在发生的事情。此问题与 returning 布尔无关。当该函数随后尝试 return 调用该函数的 "this" 对象时,发生了访问冲突。
我已经建立了断点,递归函数return很好。 return 是真的。我将发生此错误的行全部大写,因为我不知道如何突出显示它。
这里是调用递归函数的remove函数
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
它应该 return 正常,但由于某种原因它在 return 调用该函数的对象时遇到问题。由于我对函数 returns 时发生的事情的了解有限,我什至不知道如何解决这个问题。
这是因为 unique_ptr
之一的析构函数导致访问冲突。
这是因为您多次删除一个对象。当 unique_ptr 被销毁时,它也会删除它指向的对象。此外,在 unique_ptr 上调用 reset
会删除它之前指向的对象。
所以当你这样做时
while (temp->rhChild != nullptr)
{
temp.reset(temp->rhChild.get());
}
你实际上是在删除所有这些仍在树中的节点,在你查看它们之后。而且,树中的 unique_ptr (大概)仍然指向那些已删除的节点。所以你有悬挂指针的问题。