【问题标题】:Destructor of a SingleLinkedList Causing a Seg Fault导致 Seg 错误的 SingleLinkedList 的析构函数
【发布时间】:2020-09-28 02:16:46
【问题描述】:

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

我正在对我的链表类运行测试以确保它正常运行,并且在测试 PushFront 方法时遇到了问题。当我从测试函数中删除delete list 行时,我意识到析构函数导致了段错误,并且它运行良好而没有段错误(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

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

【问题讨论】:

  • 这是一组非常好的诊断信息。您已经跟踪了循环的进度并记录了即将删除的地址。但是,您错过了节点析构函数中delete 之前的诊断。像std::cout &lt;&lt; "A node is deleting " &lt;&lt; next_ &lt;&lt; "." &lt;&lt; std::endl; 这样的东西是合理的和信息丰富的。 (根据 Remy 的回答,您可能已经意识到这一点,但我仍然认为我会提到它。)

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


【解决方案1】:

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

delete next_;

只要您的CSingleLinkedList 类delete 是一个节点,该节点和所有后续节点就会被释放,因为您正在调用递归销毁。

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

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

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

    delete head_;
}

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

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

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 2013-04-30
    • 1970-01-01
    • 2015-09-22
    • 2011-07-19
    • 2014-02-17
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多