C语言链表释放内存报double free in tcache 2错误求解
问题排查结果
你的代码存在3个核心逻辑错误,同时触发了重复释放崩溃和内存泄漏问题:
- 遍历打印链表的循环执行结束后,
iter指针最终会被赋值为NULL,此时执行free(iter)等价于释放空指针。C标准规定free(NULL)不会产生任何实际操作,这行代码属于完全无效的释放逻辑。 - 执行
add_front(head, new_node)后,头指针head已经被更新为指向new_node对应的堆内存(即存储值"B"的节点),此时head和new_node保存的是完全相同的内存地址。先后执行free(new_node)和free(head)属于对同一块内存重复释放,直接触发free(): double free detected in tcache 2 Aborted (core dumped)崩溃。 - 最初通过
malloc生成的存储值"A"的节点,在插入新节点后由head->next指向,原有的释放逻辑完全没有覆盖到这块内存,这就是valgrind提示112字节确定泄漏的来源——该大小刚好是node结构体内存对齐后的占用空间,对应你代码第13行申请的第一个节点。
你之前尝试仅释放iter加head/new_node其中一个时,程序没有崩溃是因为避开了重复释放逻辑,但始终只释放了存储"B"的1个有效节点,存储"A"的节点一直未被回收,所以valgrind会提示堆泄漏。
修复方案
链表的内存释放不能靠提前保存几个节点指针单独释放,必须顺着节点的next指针逐一遍历完成:释放当前节点前必须提前保存下一个节点的地址,避免当前节点释放后丢失后续节点的访问路径。
把原代码中free(iter); free(new_node); free(head);这三行替换为如下遍历释放逻辑即可:
node *current = head; while (current != NULL) { node *next_tmp = current->next; // 提前暂存下一个节点地址,避免断链 free(current); current = next_tmp; }
修复后不会再出现重复释放问题,所有申请的节点内存都会被正确回收,valgrind检测将无内存泄漏、无非法内存操作报错。注意修复后不需要单独保留对iter、new_node的释放操作,遍历过程会自动覆盖所有申请的节点内存。
内容的提问来源于stack exchange,提问作者nullPointer
相关产品推荐
相关产品推荐

