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

C语言中二维数组使用realloc引发堆损坏问题求助

堆损坏错误(0xC0000374)排查与修复

我编写了一个用于枚举2D ASCII迷宫并将其转换为图的C函数,迷宫以#表示墙体、空白区域为可行走路径、S为起点、E为终点。该函数运行时抛出0xC0000374错误(推测为堆损坏),怀疑问题出在用于扩容二维数组的realloc调用处。以下是函数代码及field结构体定义:

结构体定义

typedef struct field {
    int x, y, free_spaces;
    int **empty_coords;
    int S[2];
    int E[2];
} field;

field *field_pointer;

原函数代码

/* Enumerates the whole field by saving the coordinates of the free pieces and the dimensions */
void enum_field(char *filename) {
    FILE *maze;
    maze = fopen(filename, "r");
    int i = 0, j = 0, chr;
    field_pointer = (field *)malloc(sizeof(field *));

    field_pointer->empty_coords = (int **)malloc(sizeof(int *));
    field_pointer->free_spaces = 0;

    while ((chr = fgetc(maze)) != EOF) {
        if (chr == '\n') {
            i = 0;
            j++;
        } else {
            if (chr != '#') {
                field_pointer->empty_coords[field_pointer->free_spaces] = (int *)malloc(2 * sizeof(int));
                field_pointer->empty_coords[field_pointer->free_spaces][0] = i;
                field_pointer->empty_coords[field_pointer->free_spaces][1] = j;
                field_pointer->free_spaces++;
                // 怀疑错误在这里
                field_pointer->empty_coords = (int **)realloc(field_pointer->empty_coords,
                                                              (field_pointer->free_spaces + 1) * sizeof(int *));

                if (chr == 'E') {
                    field_pointer->E[0] = i;
                    field_pointer->E[1] = j;
                } else if (chr == 'S') {
                    field_pointer->S[0] = i;
                    field_pointer->S[1] = j;
                }
            }
            i++;
        }
    }
    field_pointer->x = i;
    field_pointer->y = j;

    fclose(maze);
}

核心错误点

  • 结构体内存分配错误:
    初始化field_pointer时,使用malloc(sizeof(field *))仅分配了一个指针的内存,但field是完整结构体,需要分配整个结构体的空间,正确写法应为malloc(sizeof(field))。这个错误会导致结构体后续成员(如S、E数组)写入时越界,直接损坏堆结构,触发0xC0000374错误。

  • realloc风险未处理:
    直接将realloc返回值赋值给原指针,若realloc失败返回NULL,会丢失原empty_coords指针,造成内存泄漏,后续访问还会触发空指针错误。

  • 文件打开无错误检查:
    fopen可能因文件不存在、权限问题失败,直接使用未初始化的maze指针会导致未定义行为。

  • 迷宫尺寸计算逻辑漏洞:
    若迷宫最后一行无换行符,x值正确;若最后一行有换行符,i会被重置为0,导致field_pointer->x被错误设为0。


修复后的代码

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

typedef struct field {
    int x, y, free_spaces;
    int **empty_coords;
    int S[2];
    int E[2];
} field;

field *field_pointer;

void enum_field(char *filename) {
    FILE *maze = fopen(filename, "r");
    if (!maze) {
        perror("Failed to open file");
        return;
    }

    int i = 0, j = 0, chr;
    // 分配完整field结构体内存
    field_pointer = malloc(sizeof(field));
    if (!field_pointer) {
        perror("Failed to allocate field");
        fclose(maze);
        return;
    }

    // 初始分配1个int*空间
    field_pointer->empty_coords = malloc(sizeof(int *));
    if (!field_pointer->empty_coords) {
        perror("Failed to allocate empty_coords");
        free(field_pointer);
        fclose(maze);
        return;
    }
    field_pointer->free_spaces = 0;
    int max_x = 0; // 记录最大行宽修正尺寸计算

    while ((chr = fgetc(maze)) != EOF) {
        if (chr == '\n') {
            if (i > max_x) max_x = i;
            i = 0;
            j++;
        } else {
            if (chr != '#') {
                // 分配当前坐标内存
                int *coord = malloc(2 * sizeof(int));
                if (!coord) {
                    perror("Failed to allocate coord");
                    fclose(maze);
                    return;
                }
                coord[0] = i;
                coord[1] = j;
                field_pointer->empty_coords[field_pointer->free_spaces] = coord;
                field_pointer->free_spaces++;

                // 用临时变量接收realloc结果,避免丢失原指针
                int **temp = realloc(field_pointer->empty_coords, (field_pointer->free_spaces + 1) * sizeof(int *));
                if (!temp) {
                    perror("Failed to realloc empty_coords");
                    fclose(maze);
                    return;
                }
                field_pointer->empty_coords = temp;

                if (chr == 'E') {
                    field_pointer->E[0] = i;
                    field_pointer->E[1] = j;
                } else if (chr == 'S') {
                    field_pointer->S[0] = i;
                    field_pointer->S[1] = j;
                }
            }
            i++;
        }
    }
    // 处理最后一行无换行的情况
    if (i > max_x) max_x = i;
    field_pointer->x = max_x;
    field_pointer->y = j + 1; // 行数为换行次数+1

    fclose(maze);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 10:27:48