单链表删除值小于后继节点元素时触发double free错误,如何解决?
单链表删除元素触发double free错误的问题排查
你编写的删除单链表中值小于后继节点元素的函数,触发free():double free detected in tcache 2错误,核心问题出在指针初始化和删除后的指针更新逻辑上,具体问题如下:
代码中的错误点
- prev指针未初始化,处理首节点时访问非法内存:函数启动时
curr指向链表头节点、next指向第二个节点,但prev未赋值属于野指针。如果首节点满足curr->num < next->num,执行prev->next=next会直接访问非法内存,破坏内存结构,后续操作必然出错。 - 删除节点后的指针更新逻辑错误,引发重复释放:删除
curr节点后,代码将curr赋值为prev并continue,此时next仍指向原来的后继节点。下一次循环会错误地用旧的next和新的curr(即prev)比较,后续操作可能重复处理节点,甚至释放已经被释放的内存,直接触发double free。 - 未处理头节点被删除的场景:函数参数是值传递的指针,如果头节点被删除,main函数中的
first指针不会同步更新,仍指向已释放的内存,存在潜在的内存访问风险。
修正后的代码
#include <iostream> using namespace std; struct Elem { int num; Elem* next; }; // 使用引用传递指针,确保头节点被删除时能同步更新外部指针 void deleteFromLinkedList(Elem* &list) { Elem* curr = list; Elem* prev = nullptr; while (curr != nullptr && curr->next != nullptr) { Elem* nextNode = curr->next; if (curr->num < nextNode->num) { // 处理头节点被删除的情况 if (prev == nullptr) { list = nextNode; } else { prev->next = nextNode; } delete curr; // 更新curr为后继节点,继续检查新节点 curr = nextNode; } else { // 无需删除,正常移动指针 prev = curr; curr = nextNode; } } } int main() { Elem* first = nullptr, * last = nullptr, * p; int i; cout << "Enter any number or 0 to finish: "; cin >> i; while (i != 0) { p = new Elem; p->num = i; p->next = nullptr; if (first == nullptr) { first = last = p; } else { last->next = p; last = last->next; } cout << "Enter any number or 0 to finish: "; cin >> i; } deleteFromLinkedList(first); // 可选:打印处理后的链表验证结果 Elem* temp = first; while (temp != nullptr) { cout << temp->num << " "; temp = temp->next; } cout << endl; // 释放剩余节点,避免内存泄漏 temp = first; while (temp != nullptr) { Elem* toDelete = temp; temp = temp->next; delete toDelete; } first = nullptr; last = nullptr; return 0; }
修正说明
- 将函数参数改为
Elem* &list引用传递,确保头节点被删除时,main函数中的first指针能同步更新。 - 初始化
prev为nullptr,明确区分头节点删除的场景。 - 删除节点后,将
curr更新为nextNode,继续检查新节点和它的后继,避免指针混乱。 - 增加了链表剩余节点的释放逻辑,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Arsenyev01
相关产品推荐
相关产品推荐

