如何解决C程序中将文本文件数据加载到结构体数组时的内存泄漏问题
核心问题说明
C语言没有自动垃圾回收机制,所有通过malloc/calloc/realloc申请的堆内存,都需要开发者手动调用free释放,函数退出只会回收栈内存,堆内存不会自动释放,这是你出现内存泄漏的根本原因。
现有代码的问题汇总
- 内存申请逻辑错误
- 二级指针lines的初始申请容量计算错误:
char** lines = malloc(ar_length);实际应该申请ar_length * sizeof(char*)字节,才能存下ar_length个char类型指针,原写法会导致数组越界,触发未定义行为。 - 扩容判断条件完全错误:
if(line_counter > sizeof(lines))中sizeof(lines)是指针本身的大小(64位系统为8,32位为4),和你申请的数组容量ar_length毫无关系,导致扩容逻辑完全失效。 realloc用法存在泄漏风险:直接将realloc返回值赋值给原指针,如果realloc申请失败返回NULL,会丢失原指针指向的内存地址,导致直接泄漏。
- 二级指针lines的初始申请容量计算错误:
- 内存未正确释放
- 存储行指针的lines数组本身的内存,在process调用完成后没有释放,直接泄漏。
- 每行申请的256字节内存,被结构体A的
name/desc成员直接引用,你当前只释放了结构体数组arr本身的内存,没有释放每个元素引用的字符串内存,导致大量泄漏。
- 其他语法错误
- main函数中
int* length = 0;写法错误,length应该是int类型变量,而非空指针,原写法会触发段错误。 - main中调用的
betolt函数名和实际实现的load不符,属于笔误。
- main函数中
修复方案
1. 修正load函数
A* load(char* file_name, int* length) { FILE* fp = fopen(file_name, "r"); if (fp == NULL) return NULL; size_t ar_length = 500; size_t line_counter = 0; // 修正申请容量:申请ar_length个char*的空间 char** lines = malloc(ar_length * sizeof(char*)); if(lines == NULL) { fclose(fp); return NULL; } char line[256]; while (fgets(line, sizeof(line), fp)) { lines[line_counter] = malloc(256); if(lines[line_counter] == NULL) { // 申请失败释放已有内存再返回 for(int i=0;i<line_counter;i++) free(lines[i]); free(lines); fclose(fp); return NULL; } strcpy(lines[line_counter], line); line_counter++; // 修正扩容判断:当前计数达到容量上限再扩容 if(line_counter >= ar_length){ ar_length *= 2; // 用临时指针接收realloc返回值,避免申请失败丢失原内存 char** tmp = realloc(lines, ar_length * sizeof(char*)); if(tmp == NULL) { for(int i=0;i<line_counter;i++) free(lines[i]); free(lines); fclose(fp); return NULL; } lines = tmp; } } *length = line_counter; fclose(fp); A* res = process(lines, line_counter); // 释放lines数组本身的内存(仅释放存指针的数组,不释放指针指向的行内容) free(lines); return res; }
2. 新增结构体数组专用释放函数
void free_A_arr(A* arr, int length) { for(int i=0; i<length; i++) { // name和desc指向同一块行内存,只需释放一次即可,避免重复释放 free(arr[i].name); } // 最后释放结构体数组本身 free(arr); }
3. 修正main函数用法
int main(void) { A* arr; // 修正length的类型,不是指针 int length = 0; arr = load("name.txt", &length); // 你的业务逻辑 ... // 用专用函数释放内存,不要直接free(arr) free_A_arr(arr, length); return 0; }
内容的提问来源于stack exchange,提问作者D. Albert
相关产品推荐
相关产品推荐

