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
相关产品推荐
相关产品推荐

