为什么当链表节点在析构函数中删除其邻居时会发生释放后使用?

问题描述 投票:0回答:3

我在删除和析构函数方面遇到问题(我确信我在这里犯了一个愚蠢的错误,但到目前为止还无法弄清楚)。

当我单步进入析构函数并尝试在指针上调用删除时,消息显示“无法访问地址某个地址处的内存。”

相关代码为:

/*
 * Removes the front item of the linked list and returns the value stored
 * in that node.
 *
 * TODO - Throws an exception if the list is empty
 */
std::string LinkedList::RemoveFront()
{
    LinkedListNode *n = pHead->GetNext(); // the node we are removing
    std::string rtnData = n->GetData(); // the data to return

    // un-hook the node from the linked list
    pHead->SetNext(n->GetNext());
    n->GetNext()->SetPrev(pHead);

    // delete the node
    delete n;
    n=0;

    size--;
    return rtnData;
}

/*
 * Destructor for a linked node.
 *
 * Deletes all the dynamically allocated memory, and sets those pointers to 0.
 */
LinkedListNode::~LinkedListNode()
{
    delete pNext; // This is where the error pops up
    delete pPrev;
    pNext=0;
    pPrev=0;
}
c++ destructor delete-operator
3个回答
5
投票

您似乎正在从析构函数中删除列表的下一个和上一个节点。如果

pNext
pPrev
LinkedListNode*
,则意味着您正在递归删除整个列表:-(

试试这个:

std::string LinkedList::RemoveFront()
{
    LinkedListNode *n = pHead->GetNext(); // the node we are removing
    std::string rtnData = n->GetData(); // the data to return

    // un-hook the node from the linked list
    pHead->SetNext(n->GetNext());
    n->GetNext()->SetPrev(pHead);

    n->SetNext(0);
    n->SetPrev(0);
    // delete the node
    delete n;
    n=0;

    size--;
    return rtnData;
}

LinkedListNode::~LinkedListNode()
{
}

(实际上,你甚至不需要将 prev 和 next 指针重置为 0,因为无论如何你都会删除该节点。我保留这些语句是因为它们至少使节点处于一致状态,这是一个好主意一般来说。如果您稍后更改内存管理策略并决定存储未使用的节点以供以后重用,这可能会有所不同。)


1
投票

您的

LinkedListNode
似乎正在删除其邻居,因此当您删除一个节点时,它会继续销毁整个列表 - 请注意,当您删除节点时,不要将
pNext
pPrev
设置为 NULL。

即使您希望销毁整个列表,您的

LinkedListNode
析构函数也是有问题的:同时拥有
delete pNext
delete pPrev
将导致同一析构函数的多次调用(我认为最终会导致堆栈溢出) .


0
投票

实际上你不应该惹恼节点中的邻居。这是列表类要做的 - 正确连接它们。在析构函数中,您可以将它们设置为 null,但除非您动态分配了其他东西 - 您不必调用

delete

© www.soinside.com 2019 - 2024. All rights reserved.