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

为何C语言运行提示double free or corruption (out) Aborted错误

错误根因

你的代码触发double free or corruption(out)报错的核心问题是内存申请与释放的逻辑完全不匹配:

  • 构建链表时你只调用了一次malloc(4 * sizeof(node)),一次性申请了能存4个node的连续堆内存块,n是这块内存的唯一合法起始地址,4个节点都是这块连续内存里的元素,不是独立分配的堆块。
  • 释放内存时你沿着链表逐节点调用free():第一次执行free(list)时,因为list指向n[0]也就是这块内存的起始地址,已经把整个4节点占的整块堆内存完全交还给操作系统了。后续你再对同一块内存内部的n[1]、n[2]、n[3]地址调用free(),属于对非malloc返回的地址做释放、对已释放内存重复操作,直接触发堆内存校验机制中止程序。
  • 你的遍历打印逻辑本身没有指针指向错误,所以打印环节能正常输出1、2、3、4,报错只会出现在释放阶段。
修复方案

二选一即可:

方案1:匹配现有一次性分配内存的写法

既然是一次申请的连续内存,不需要逐节点释放,只需要释放一次malloc返回的原始地址即可,删掉原来的逐节点释放while循环,替换为:

free(n);
n = NULL;
list = NULL;

方案2:实现常规独立节点单链表的逐节点释放逻辑

如果要保留逐节点释放的写法,就不要一次性申请4个节点的内存,改为每个节点单独调用malloc分配,这样每个节点的地址都是malloc直接返回的合法地址,逐节点释放就不会出错,参考实现:

int main(void) {
    node *list = NULL;

    // 逐节点分配内存构建链表
    for (int val = 1; val <= 4; val++) {
        node *new_node = malloc(sizeof(node));
        if (new_node == NULL) {
            return 1;
        }
        new_node->number = val;
        new_node->next = NULL;
        
        // 追加到链表尾部
        if (list == NULL) {
            list = new_node;
        } else {
            node *cur = list;
            while (cur->next != NULL) {
                cur = cur->next;
            }
            cur->next = new_node;
        }
    }

    // 遍历打印逻辑和原代码一致
    for (node *tmp = list; tmp != NULL; tmp = tmp->next) {
        printf("%i\n", tmp->number);
    }

    // 逐节点释放合法
    while (list != NULL) {
        node *tmp = list->next;
        free(list);
        list = tmp;
    }
    return 0;
}

内存释放核心规则:传给free()的指针必须是malloc/calloc/realloc直接返回的原始起始地址,不能传入同一块堆内存内部的偏移地址,也不能对同一块堆内存重复调用free()。

内容的提问来源于stack exchange,提问作者Grgi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:45:44