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

程序编译通过但运行时触发realloc指针未分配错误排查

问题分析与修复方案

核心错误点

  • 变量声明类型不匹配:main里的monster_s *monsters[MAX_MONSTERS];是栈上的指针数组,但load_monsters_csv需要的是指向单个动态结构体数组指针的指针,用来接收realloc分配的连续内存块。这种不匹配导致realloc操作的是未初始化的野指针,触发报错。
  • 错误的内存释放操作:load_monsters_csv里的free(monsters);完全错误,monsters是传入的参数指针,并非函数内动态分配的内存;main里的free(monsters);释放的是栈上数组,属于未定义行为。
  • 缺失文件打开检查:fopen可能失败(比如文件不存在),未做判断会导致后续操作崩溃。
  • 未检查realloc返回值:内存分配可能失败,直接赋值会丢失原内存地址,造成泄漏。

修复后的代码

修正后的load_monsters_csv函数

// FUNCTION 
int load_monsters_csv(monster_s **monsters, FILE *fp) {
    int num_read = 0;
    char buffer[MAX_LEN] = { 0 };

    while (fgets(buffer, MAX_LEN, fp)) {
        trim(buffer);
        // 跳过空行
        if (buffer[0] == '\0') {
            continue;
        }

        // 用临时变量接收realloc结果,避免分配失败时丢失原内存
        monster_s *temp = realloc(*monsters, (num_read + 1) * sizeof(monster_s));
        if (temp == NULL) {
            perror("realloc failed");
            // 释放已分配的部分内存,避免泄漏
            free(*monsters);
            *monsters = NULL;
            return num_read;
        }
        *monsters = temp;

        // 解析当前行到对应的怪物结构体
        parse_monster(*monsters + num_read, buffer);
        num_read++;
    }

    return num_read;
}

修正后的main函数

// MAIN
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(int argc, char *argv[]) {
    int num_monsters = 0;
    // 声明单个指针并初始化为NULL,让realloc可以正确启动(等同于malloc)
    monster_s *monsters = NULL;

    // 验证命令行参数
    if (argc != 2) {
        printf("Must include a file name\n");
        return 1;
    }

    // 打开文件并检查是否成功
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL) {
        perror("Failed to open file");
        return 1;
    }

    // 加载所有数据
    num_monsters = load_monsters_csv(&monsters, fp);

    // 打印数据验证
    for(int i = 0; i < num_monsters; i++) {
        printf("%s (%s), %d HP, %d AC, %d STR, %d DEX, %d CON\n", 
               monsters[i].name, monsters[i].type, monsters[i].hp, monsters[i].ac, 
               monsters[i].str, monsters[i].dex, monsters[i].con);
        // 注意:如果parse_monster为name/type分配了堆内存,需在此单独free这些字段
    }

    // 释放动态分配的怪物数组
    free(monsters);
    fclose(fp);

    return 0;
}

额外注意事项

如果parse_monster函数中为monster_s的字符串字段(如name、type)分配了堆内存,在释放monsters数组前,需要循环遍历每个元素,先释放这些字符串的内存,再释放数组本身,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:01:16