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

如何解决C程序中将文本文件数据加载到结构体数组时的内存泄漏问题

核心问题说明

C语言没有自动垃圾回收机制,所有通过malloc/calloc/realloc申请的堆内存,都需要开发者手动调用free释放,函数退出只会回收栈内存,堆内存不会自动释放,这是你出现内存泄漏的根本原因。


现有代码的问题汇总

  • 内存申请逻辑错误
    1. 二级指针lines的初始申请容量计算错误:char** lines = malloc(ar_length); 实际应该申请ar_length * sizeof(char*)字节,才能存下ar_length个char类型指针,原写法会导致数组越界,触发未定义行为。
    2. 扩容判断条件完全错误:if(line_counter > sizeof(lines)) 中sizeof(lines)是指针本身的大小(64位系统为8,32位为4),和你申请的数组容量ar_length毫无关系,导致扩容逻辑完全失效。
    3. realloc用法存在泄漏风险:直接将realloc返回值赋值给原指针,如果realloc申请失败返回NULL,会丢失原指针指向的内存地址,导致直接泄漏。
  • 内存未正确释放
    1. 存储行指针的lines数组本身的内存,在process调用完成后没有释放,直接泄漏。
    2. 每行申请的256字节内存,被结构体A的name/desc成员直接引用,你当前只释放了结构体数组arr本身的内存,没有释放每个元素引用的字符串内存,导致大量泄漏。
  • 其他语法错误
    1. main函数中int* length = 0;写法错误,length应该是int类型变量,而非空指针,原写法会触发段错误。
    2. main中调用的betolt函数名和实际实现的load不符,属于笔误。

修复方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:24:06