繁体   English   中英

与二维数组一起使用时,Realloc 在 C 中产生未定义的行为

[英]Realloc produces undefined behavior in C when used with a 2d array

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++;
                // I believe the error is here V
                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);
}

好吧,所以我在这里有这个 C function,它可以帮助我枚举一个 2D ASCII 迷宫,然后我可以把它变成一个图形。 ASCII 迷宫用#表示墙壁,自由空间表示可步行的道路, S表示开始, E表示出口。 function 不起作用并抛出0xC0000374这可能意味着堆损坏。 我试图进一步调查并注意到很可能,应该扩大二维数组的realloc function 有问题。 我对 C 比较陌生,并且一直盯着我的代码看,你能帮我用另一个 POV 和新鲜的眼光来看看我可能做错了什么吗? 这也是字段结构的布局:

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

在您的初始分配中肯定存在大小问题:

field_pointer = (field *)malloc(sizeof(field *))应该分配结构的大小,而不是指针的大小。 使用field_pointer = malloc(sizeof(field))或更好:

    field_pointer = malloc(sizeof(*field_pointer));

请注意,您可以通过使用真正的 2D 数组而不是指向指向 arrays 的 2 int的指针数组的指针来简化代码。

另请注意,在完全加载之前,无需操作全局 object。 建议使用局部变量。 返回结构指针允许调用者检测加载迷宫的失败。 存储指向全局变量的指针应该是调用者的责任。

这是修改后的版本:

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

typedef struct field {
    int x, y, free_spaces;
    int (*empty_coords)[2];
    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 */
field *enum_field(const char *filename) {
    FILE *maze = fopen(filename, "r");
    if (maze == NULL)
        return NULL;
    field *fp = calloc(sizeof(*fp), 1);
    if (fp == NULL) {
        fclose(maze);
        return NULL;
    }
    fp->free_spaces = 0;
    fp->empty_coords = NULL;
    int i = 0, j = 0, chr;

    while ((chr = fgetc(maze)) != EOF) {
        if (chr == '\n') {
            if (fp->x < i)
                fp->x = i;
            i = 0;
            j++;
        } else {
            if (chr != '#') {
                // allocate space for one extra set of coordinates
                int (*new_coords)[2] = realloc(fp->empty_coords,
                                               (fp->free_spaces + 1) * sizeof(*fp->empty_coords));
                if (!new_coords) {
                    free(fp->empty_coords);
                    free(fp);
                    fclose(maze);
                    return NULL;
                }
                fp = new_coords;
                fp->empty_coords[fp->free_spaces][0] = i;
                fp->empty_coords[fp->free_spaces][1] = j;
                fp->free_spaces++;

                if (chr == 'E') {
                    fp->E[0] = i;
                    fp->E[1] = j;
                } else
                if (chr == 'S') {
                    fp->S[0] = i;
                    fp->S[1] = j;
                }
            }
            i++;
        }
    }
    fp->y = j;
    fclose(maze);
    // return structure pointer for the caller to store to into field_pointer
    return fp;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM