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

C语言链表释放报错:移除free(L)正常,保留则触发double free

问题原因分析

你的问题出在listeinit函数的实现逻辑上:

Liste listeinit(void){
    Liste *L = malloc(sizeof(Liste));
    L->taille = 0;
    L->premier = NULL;
    return *L;
}

这个函数用malloc在堆上分配了一个Liste结构体,随后返回结构体的值拷贝——堆上L指向的内存会直接泄漏,调用者拿到的是栈上生成的Liste实例。当你调用freeliste(&你的链表变量)时,传入的是栈上变量的地址,freeliste里的free(L)试图释放栈内存,这属于非法操作,直接触发了内存错误("double free or corrupt"本质是程序尝试释放不属于堆的内存区域)。

修复方案

有两种可行的修复方式,选一种适配你的使用场景即可:

方案一:让listeinit返回堆指针

修改listeinit的返回类型为指针,让调用者直接拿到堆上的结构体指针,这样freeliste里的free(L)操作就合法了:

// 修改返回类型为Liste*
Liste* listeinit(void){
    Liste *L = malloc(sizeof(Liste));
    if (L == NULL) { // 新增内存分配失败的判断
        printf("Erreur en attribuant la memoire pour la liste");
        return NULL;
    }
    L->taille = 0;
    L->premier = NULL;
    return L;
}

// 调用示例:
// Liste *maListe = listeinit();
// if (maListe != NULL) { ... }

对应的freeliste函数无需修改,因为此时传入的L是堆上的合法指针。

方案二:栈上初始化链表结构体

如果不需要在堆上分配Liste结构体,直接在栈上完成初始化,同时删掉freeliste里的free(L)语句:

// 直接返回栈上初始化的结构体
Liste listeinit(void){
    Liste L;
    L.taille = 0;
    L.premier = NULL;
    return L;
}

// 修改freeliste,移除free(L)
void freeliste(Liste *L){
    while(L->premier != NULL){
      Element *a = L->premier;
      L->premier = L->premier->next;
      free(a);
    }
    // 此处不再free(L),因为L指向栈内存,无需手动释放
}

这种方式下,调用者直接声明Liste maListe = listeinit();即可,maListe本身在栈上,函数结束后会自动销毁。

额外优化建议:inseretete里的字符串拷贝逻辑可以用strncpy简化,既简洁又能避免数组越界:

strncpy(ele->chaine, x, sizeof(ele->chaine)-1);
ele->chaine[sizeof(ele->chaine)-1] = '\0'; // 强制保证字符串结尾

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 14:40:23