初始化嵌套结构
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;
我在尝试初始化嵌套结构时遇到问题。
编译时没有错误,但执行时出现段错误。 在 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;