初始化嵌套结构

Initializing nested structures

我在尝试初始化嵌套结构时遇到问题。

编译时没有错误,但执行时出现段错误。 在 valgrind 中,我得到

> Invalid read of size 8  at 0x402175: new_animal  
  > Address 0x38 is not stack'd, malloc'd or (recently) free'd

这是代码:

    void new_animal(int i, int j, int species){

   struct animal * a;

    if (array[i][j]==NULL) 
    {
        a = malloc(sizeof(struct animal));
        assert (a);
        a->espece=espece;
        if(array[i][j]->player==NULL)
        {
        a->player->id_fisherman=0;
        strcpy(a->player->Name,"N"); //I want it set to NULL.
        }
    }
   grille[i][j] = a;
  }

这是两个结构:

struct fisherman {
    int id_fisherman;
    char Name[10];
};

struct animal {
    int species;
    struct fisherman* player;
};

在我添加渔夫之前一切正常。不知道是内存分配的问题,还是初始化的时候。

a->player = malloc(sizeof(struct fisherman));

您需要先为 struct Fisherman 分配内存,然后再向其写入内容

问题之一在这里:

if (array[i][j]==NULL) {
    // ... then ...
    if(array[i][j]->player==NULL)
}

如果 array[i][j]NULL,那么您不能取消引用它。您必须先将其分配给一个有效的指针。

让我们按照代码分成几个部分来解释。

当您执行 a = malloc(sizeof(struct animal)); 时,您在 物种 [= 上具有 0 的结构55=] 属性,以及 player 属性上的 memory garbage,因为它是一个未初始化的指针。

正如@Gopi所说,你必须在使用它之前初始化这个指针:

a->player = malloc(sizeof(struct fisherman));

现在,以下声明有效:

a->player->id_fisherman=0;

在使用指针之前,如a->player,最好断言它。 C 编译器在可能的 运行 时间错误检测方面不是很可靠。在生产代码中,您可以将编译器设置为不断言。

避免此类错误的一个技巧是在定义结构的同时创建一个初始化函数。 你可以这样写:

struct fisherman {
        int id_fisherman;
        char Name[10];
};

*fisherman malloc_fisherman(){
        return malloc(sizeof(struct fisherman));
}

*fisherman malloc_fisherman(int id){
        struct fisherman *a = malloc(sizeof(struct fisherman));
        a->id_fisherman = id;
        return a;
}

在这里,您将创建两个函数,一个用于默认创建,另一个用于创建具有给定参数的结构。 struct animal 可以依赖这些函数来创建自己的函数。

Philip Guo 撰写了一篇关于基本 C 编程良好实践的精彩文章。 Check it out,特别是部分使用断言语句来记录和执行函数前置条件和其他假设

OBS:下面的说法是不是错了?属性名称不是 species 而不是 espece

a->espece=espece;