You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:54:19