导致段错误的SingleLinkedList的析构函数

问题描述 投票:1回答:1

我正在用c ++编写单链列表,当单链列表中包含多个节点的列表上的析构函数被调用时,我的单链列表的析构函数会导致段错误。

我正在我的链表类上运行测试以确保其正常运行,并且在测试PushFront方法时遇到了问题。当我从测试功能中删除delete list行时,我意识到析构函数会导致seg故障,并且在没有segfaulting的情况下运行良好(PushFront测试功能只是一系列测试功能中的一个功能,可以测试测试的所有方面链接列表。删除删除行后,调用此系列测试功能的测试程序可以很好地完成执行,但是使用删除行会导致段错误。

这是链接列表的析构函数(带有用于调试目的的cout语句:]

// CSingleLinkedList Destructor
CSingleLinkedList::~CSingleLinkedList()
{
    std::cout << "In Destructor" << std::endl;

    CSingleLinkedList::CSingleLinkedNode* temp = head_;

    std::cout << "temp = " << temp << std::endl;

    while(temp != nullptr)
    {
        CSingleLinkedList::CSingleLinkedNode* toDelete = temp;
        temp = temp->GetNext();

        std::cout << "toDelete = " << toDelete << std::endl;
        std::cout << "temp = " << temp << std::endl;

        delete toDelete;
    }
}

这是链接节点的析构函数(它仅具有数据成员value_(一个int)和next_(指向下一个CSingleLinkedNode的指针):

// CSingleLinkedNode Destructor
CSingleLinkedList::CSingleLinkedNode::~CSingleLinkedNode()
{
    delete next_;
}

这是我正在测试PushFront功能的测试功能:

void TestListPushFront()
{
    CSingleLinkedList* list = new CSingleLinkedList();

    list->PushFront(1);

    assert(list->GetFrontValue() == 1);
    assert(list->GetBackValue() == 1);
    assert(list->GetSize() == 1);

    list->PushFront(2);
    list->PushFront(3);

    assert(list->GetFrontValue() == 3);
    assert(list->GetBackValue() == 1);
    assert(list->GetSize() == 3);

    std::cout << "TestListPushFront Passed!" << std::endl;

    delete list;
}

这是运行函数时看到的轨迹:

TestListPushFront Passed!
In Destructor
temp = 0x55ce050332e0
toDelete = 0x55ce050332e0
temp = 0x55ce050332c0
toDelete = 0x55ce050332c0
temp = 0x55ce050332a0
Segmentation fault

任何人都对为什么发生此段错误有任何想法?

c++ linked-list segmentation-fault singly-linked-list
1个回答
3
投票

您的CSingleLinkedNode析构函数具有以下语句:

delete next_;

[CSingleLinkedListdelete一旦成为一个节点,该节点和所有后续节点将被释放,因为您正在调用递归销毁

同样,当您的CSingleLinkedList析构函数销毁head_节点,然后尝试访问next节点时,由于该next >>节点已已经销毁,它崩溃了。这就是您的段错误的来源。

相反,您的CSingleLinkedList析构函数本身必须是单个delete语句:

CSingleLinkedList::~CSingleLinkedList()
{
    std::cout << "In Destructor" << std::endl;

    delete head_;
}

但是,在链表中使用递归析构函数从来都不是一个好主意,尤其是当链表中有大量节点时。这可能会导致堆栈溢出,因为每次对CSingleLinkedNode析构函数的递归调用都会将越来越多的数据压入调用堆栈,直到到达列表的末尾或调用堆栈空间不足为止。 >

在处理链表中的节点时始终使用迭代循环-就像您的CSingleLinkedList析构函数要进行[[trying

”一样。为了使该循环正常工作,您需要从delete next_;析构函数中删除CSingleLinkedNode语句。节点与破坏其他节点无关。这是他们的父级列表类负责管理的职责。
© www.soinside.com 2019 - 2024. All rights reserved.