链表删除最常见错误是释放后未更新前驱节点next指针导致悬垂指针;须先解链(prev->next = curr->next)、再delete、最后置nullptr,头节点删除必须更新head本身。

删除节点时忘记把前驱指针置空,导致悬垂指针
最常见错误不是没释放内存,而是释放后没更新前驱节点的 next 指针。比如删中间节点时只写了 delete p,但没让上一个节点的 next 指向被删节点的 next,结果后续访问 prev->next->val 就崩了。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 删除前务必确认前驱存在:头节点要单独处理,不能硬写
prev->next = curr->next - 统一用双指针遍历:用
prev和curr,删curr时先执行prev->next = curr->next,再delete curr - 删完立刻把指针设为
nullptr(尤其在调试阶段):比如curr = nullptr,避免误用已释放地址
头节点删除必须更新 head 指针本身
很多人以为“链表 head 是个指针,删头节点只要 delete head 就行”,结果程序跑着跑着就段错误——因为 head 还指着那块已释放内存,下次遍历时直接踩进去。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 头节点删除必须重赋值
head:如Node* tmp = head; head = head->next; delete tmp; - 如果函数参数是
Node*& head,就能直接改head;若只是Node* head,函数内修改无效,调用方的head仍悬垂 - 别依赖 RAII 自动清理:C++ 原生链表不带析构逻辑,
head是裸指针,不会自动清空或跳转
delete 后继续访问 next 或 val 就是未定义行为
典型现象:删完节点后还打印 curr->val 或走 curr->next,程序可能暂时不崩(尤其 Debug 模式下内存没立刻覆写),但上线后随机 crash,极难复现。
实操建议:
立即学习“C++免费学习笔记(深入)”;
-
delete必须是该节点最后一次使用:所有对curr->xxx的访问都得在delete curr之前完成 - 释放顺序要严格:先解链(更新前后指针),再释放(
delete),绝不颠倒 - 用 AddressSanitizer 编译:加
-fsanitize=address,能当场报出 “heap-use-after-free” 错误
单链表析构函数里漏掉循环释放
只写 delete head; 不等于清空整个链表——它只释放第一个节点,其余全泄露。Valgrind 会明确报 definitely lost。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 析构必须 while 循环:从
head开始,每次保存next,再delete curr,最后更新curr = next - 别用递归析构:深度大时栈溢出,尤其没尾递归优化的编译器
- 释放后把
head设为nullptr:防止二次析构,也方便调试时判断是否已清理
真正麻烦的不是写几行 delete,而是每个 delete 都得配套一次指针更新、一次边界检查、一次访问顺序校验。少一个环节,问题就藏进偶发崩溃里,等你凌晨三点对着 core dump 发呆。










