C语言单链表删除指定值节点时尾节点触发double free错误求解
问题成因
你遇到的double free报错核心是代码未处理待删除节点为头节点的边界场景,且该场景刚好发生在你删除尾节点的测试用例中:
- 代码中前驱指针
pr和遍历指针cur的初始值都为头节点head,当待删除节点就是头节点时,你直接free(cur)后仍然返回指向已释放内存的原head指针,形成野指针 - 当你删除尾节点触发报错时,对应的测试用例大概率是链表只有一个节点(头节点同时是尾节点),后续调用者对返回的野指针做遍历、释放等操作时,就会触发释放后使用(UAF),甚至重复释放同一内存块,和你贴的报错信息完全吻合
- 非头节点的删除逻辑(包括非头的尾节点删除)本身没有问题,这也是你观察到待删除节点不是尾节点时运行正常的原因
修复方案
修改点说明
- 单独处理头节点匹配的边界情况,删除头节点后直接返回更新后的新头节点
- 非头节点的删除逻辑可以简化,无需单独判断是否为尾节点:尾节点的
next本身就是NULL,直接赋值给前驱节点的next即可 - 调用方需要用原头指针接收函数返回值,避免头节点删除后仍持有野指针
修复后代码
node *delete(node* head, int value) { // 处理空链表边界 if (head == NULL) { return NULL; } // 处理头节点匹配的情况 if (head->val == value) { node *temp = head; head = head->next; free(temp); return head; } // 遍历处理非头节点 node *pr = head; for (node *cur = head->next; cur != NULL; cur = cur->next) { if (cur->val == value) { pr->next = cur->next; free(cur); return head; } pr = cur; } // 未找到匹配节点直接返回原头节点 return head; }
调用示例
// 正确写法,用原头指针接收返回值 head = delete(head, 5);
内容的提问来源于stack exchange,提问作者faelex
相关产品推荐
相关产品推荐

