我正在用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
任何人都对为什么发生此段错误有任何想法?
您的CSingleLinkedNode
析构函数具有以下语句:
delete next_;
[CSingleLinkedList
类delete
一旦成为一个节点,该节点和所有后续节点将被释放,因为您正在调用递归销毁。
同样,当您的CSingleLinkedList
析构函数销毁head_
节点,然后尝试访问next节点时,由于该next >>节点已已经销毁,它崩溃了。这就是您的段错误的来源。
相反,您的CSingleLinkedList
析构函数本身必须是单个delete
语句:
”一样。为了使该循环正常工作,您需要从CSingleLinkedList::~CSingleLinkedList() { std::cout << "In Destructor" << std::endl; delete head_; }
但是,在链表中使用递归析构函数从来都不是一个好主意,尤其是当链表中有大量节点时。这可能会导致堆栈溢出,因为每次对
CSingleLinkedNode
析构函数的递归调用都会将越来越多的数据压入调用堆栈,直到到达列表的末尾或调用堆栈空间不足为止。 >在处理链表中的节点时始终使用迭代循环-就像您的
CSingleLinkedList
析构函数要进行[[trying
delete next_;
析构函数中删除CSingleLinkedNode
语句。节点与破坏其他节点无关。这是他们的父级列表类负责管理的职责。