c++ - SingleLinkedList 的析构函数导致段错误

标签 c++ linked-list segmentation-fault singly-linked-list

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

我正在我的链表类上运行测试,以确保它正常运行,并且在测试 PushFront 方法时遇到了问题。当我从测试函数中删除 delete list 行时,我意识到析构函数导致了段错误,并且它运行良好,没有出现段错误(PushFront 测试函数只是一系列多个测试函数中的一个函数)来测试链表的各个方面。删除delete行后,调用这一系列测试函数的测试程序完美地完成执行,但删除行后,会导致段错误。

这是链表的析构函数(带有用于调试目的的 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

有人知道为什么会发生这个段错误吗?

最佳答案

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

delete next_;

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

因此,当您的 CSingleLinkedList 析构函数销毁 head_ 节点,然后尝试访问下一个节点时,它会崩溃,因为>下一个节点已经被破坏。这就是你的段错误的来源。

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

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

    delete head_;
}

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

在处理链表中的节点时始终使用迭代循环 - 就像您的 CSingleLinkedList 析构函数尝试所做的那样。为了使该循环正常工作,您需要从 CSingleLinkedNode 析构函数中删除 delete next_; 语句。节点无权破坏其他节点。这是其父列表类的责任来管理。

关于c++ - SingleLinkedList 的析构函数导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62273529/

相关文章:

C++ Magnitude (Normalise) 似乎不正确

c++ - 单链表的困惑

c++ - 在成员函数之间传递 const 变量作为数组的索引

c - 如何使用具有多个变量的结构初始化链表

c++ - 线程安全的 vector 和字符串容器?

c++ - 系统 ("pause"); - 为什么错了?

c - 通过循环遍历 vector 链接列表,使用 opengl1 绘制线条

c - 为什么我销毁列表后尾部仍然指向 Something 而不是指向 NULL

c - 由终端参数引起的段错误

C 编程,将结构体中的 int 成员分配给整数时出现段错误