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
相关产品推荐
相关产品推荐

