在malloc的Sigsegv

时间:2017-11-17 14:48:21

标签: c pointers memory struct malloc

我想保存一个包含我用作动态数组的指针的结构但是当我加载struct和malloc这个指针时,它会失败。

我有三个结构(Orientation,ShipType,Status和PlayerType是枚举,你可以用Int替换它们):

struct Map
{
    int width, height;
    int* cases;
};
typedef struct Map Map;

struct Ship
{
    int x, y, length, firstShoot, color;
    int hasBeenDiscovered;
    Orientation orientation;
    ShipType type;
    Status status;
};
typedef struct Ship Ship;

struct Player
{
    int activeShips;
    Map map[2];
    char lastMoves[5][128];
    Ship ships[10];
    PlayerType type;
    int shipcolor[4];
    int color;
};
typedef struct Player Player;

我声明了一个2 Player的数组,如下所示:Player players[2];并初始化它们的属性。然后我想将结构保存在一个文件中,以便以后加载它。 另外,我使用Map结构作为2d动态数组,使用四个函数:

void mallocMap(Map* map, int width, int height)
{
    map->cases = malloc(sizeof(int) * width * height);

    map->width = width;
    map->height = height;

    if (map->cases == NULL)
    {
        printf("Erreur d'allocation de memoire\n");
        exit(0);
    }
}

void freeMap(Map* map)
{
    free(map->cases);
}

int getMapValue(Map map, int x, int y)
{
    return *(map.cases + y*map.width + x);
}

void setMapValue(Map* map, int value, int x, int y)
{
    *(map->cases + y*map->width + x) = value;
}

因此,当我存储结构时,map.cases只是一个指针,我需要将值分别存储在其地址中,如下所示:

int save(Player players[2])
{
    int* i;
    FILE* file = NULL;

    file = fopen("save.txt","w+");

    if (file != NULL)
    {
        fwrite(players, sizeof(Player), 2, file);

        fwrite(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
        fwrite(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
        fwrite(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
        fwrite(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
    }
    else
    {
        // error
    }

    fclose(file);

    return 1;
}

每个玩家都有2张地图,所以最后有4张地图存放。 问题出在我的load()函数中:

int load(Player players[2])
{
    FILE* file = NULL;

    file = fopen("save.txt","r");

    if (file != NULL)
    {
        int *i;

        fread(players, sizeof(Player), 2, file);    

        mallocMap(&players[0].map[0], players[0].map[0].width, players[0].map[0].height);
        mallocMap(&players[0].map[1], players[0].map[1].width, players[0].map[1].height);
        mallocMap(&players[1].map[0], players[1].map[0].width, players[1].map[0].height);
        mallocMap(&players[1].map[1], players[1].map[1].width, players[1].map[1].height);

        fread(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
        fread(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
        fread(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
        fread(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);

    }
    else
    {
        // error
    } 

    fclose(file);

    return 1;
}

当我拨打mapAlloc()时,它无法分配内存和exit(0);我的程序停止了。

1 个答案:

答案 0 :(得分:1)

您宣布load功能的方式并不合适:

int load(Player* players[2])

这需要一个指向Player 的指针数组,而你的save例程需要一个Player数组(即Player players[2])。您可能需要将其更改为:

int load(Player players[2])

您还要将值重新读回错误的地址:

    for(i = players[0]->map[0].cases; i < players[0]->map[0].cases + players[0]->map[0].width * players[0]->map[0].height; i++)
        fread(&i, sizeof(int), 1, file);

您已将fread的地址传递给i。这意味着您正在int中阅读并将其存储在i中,这是一个本地int *您想要的动态分配数组写信给。

在此处删除地址运算符并直接传递i,就像使用fwrite

时一样
        fread(i, sizeof(int), 1, file);

这会将您读入的int写入数组。

此外,这里不需要使用循环来读/写单个int。只需执行一次读/写传递数值即可读/写。

所以储蓄将是:

fwrite(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fwrite(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fwrite(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fwrite(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);

加载将是:

fread(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fread(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fread(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fread(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);

编译代码时,不应该有任何警告。如果有,你可能做错了你需要解决的问题。