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

动态结构体数组无需realloc即可无限读取?请求排查代码问题

结构体动态读取文件的问题排查

结构体定义

typedef struct myprog
{
    int id;
    char name[100];
    int price;
}myprog;

读取函数

myprog* readFromFile(FILE* fP, char fileName[], myprog* reg, int* size)
{
    fP = fopen(fileName, "r");      // 以只读方式打开输入文件

    if (fP == NULL)   // 如果文件未找到,则不执行任何操作
    {
        printf("File does not exist.");
    }
    else    // 否则逐行读取文件内容
    {
        printf("\n正在从文件读取数据");
        int x = 0;
        char line[100];
        char* split;
        char* args[4];
        while (fgets(line, 100, fP))  // 读取文件行内容
        {
            if (x == MAX)    // 如果达到最大容量,则将容量翻倍
            {
                int new_size = MAX * 2;
                reg = (struct vara*)realloc(reg, new_size * sizeof(struct vara));   // 即使注释这些行代码也能运行 :O
            }

            split = strtok(line, " ");      // 以空格为分隔符拆分行内容,例如{"1", "apple", "10"}
            args[0] = split;

            int i = 1;
            while (split != NULL)
            {
                split = strtok(NULL, " ");
                args[i] = split;
                i++;
            }

            if (i != 3) // 检查参数数量是否为三个
            {
                // 将参数复制到结构体
                reg[x].id = atoi(args[0]);  // 复制编号
                strcpy(reg[x].name, args[1]);   // 复制名称
                reg[x].price = atoi(args[2]);  // 复制价格
                x++;
            }
        }
        (*size) = x;
        printf("\n读取完成!");
        fclose(fP);
    }
    return reg;
}

主函数

void main()
{
    char fileName[100];
    FILE* fP = NULL;
    printf("Enter file Name : ");
    scanf("%s", fileName);
    myprog* reg = malloc(MAX * sizeof * reg); // #define MAX 1
    int size = 0;
    reg = readFromFile(fP, fileName, reg, &size);
    // 以下为其他代码
}

输入文件示例

1 prod_a 15
2 prod_b 20

遇到的问题

当MAX定义为1时,代码可以读取文件中任意数量的产品,且无内存泄漏错误。即使注释掉realloc相关代码,程序依然能正常运行,请求找出代码中的错误。


错误点分析

  • 结构体类型不匹配:realloc时错误使用了struct vara,但实际定义的结构体是myprog,类型转换错误导致内存分配逻辑完全失效。
  • 扩容条件错误:判断条件为x == MAX,但MAX是固定值1,只会在x=1时触发一次扩容;且扩容后未更新容量变量,后续x超过新容量时不会再触发扩容,直接引发数组越界。
  • 参数检查逻辑颠倒:代码中if (i != 3)才执行赋值,但正确行拆分后i的值应为3(拆分3个字段后split变为NULL,i自增到3),这会导致正确行被跳过,错误行反而被处理。若行格式错误,args数组可能存在NULL指针,调用atoi(NULL)或strcpy(NULL)会触发未定义行为。
  • 数组越界的未定义行为:MAX=1时初始仅分配1个myprog的内存,但读取多行时直接访问reg[x](x≥1)属于越界访问。程序能运行只是运气好,内存未被其他数据覆盖,并非真的无问题,随时可能崩溃或出现异常结果。
  • realloc失败未处理:未检查realloc的返回值,若内存分配失败会返回NULL,导致原reg指针丢失,引发内存泄漏。
  • 主函数不符合标准:void main不是C标准的主函数定义,应使用int main()并返回0。
  • 冗余参数传入:函数中的FILE* fP是传值参数,函数内重新赋值不会影响主函数,完全可在函数内部定义该变量,无需作为参数传入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:30:52