我有这个示例文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char *name;
} player;
void
playercreation(player *p, int nr)
{
p=malloc(sizeof(player));
char stringtemp[10];
printf("Create player %d:\nWrite your name (max 10 letters): ", nr);
scanf("%s", stringtemp);
p->name=malloc(sizeof(*(p->name))*11);
strcpy(p->name, stringtemp);
p->drawnlines=0;
p->squares=0;
}
void
playercreationMenu(player *p1, player *p2)
{
playercreation(p1, 1);
playercreation(p2, 1);
}
void
confirmPlayer(player *p)
{
printf("player %s created\n", p->name);
}
int
main(void)
{
player p1, p2;
playercreationMenu(&p1, &p2);
confirmPlayer(&p1);
confirmPlayer(&p2);
}
在我的真实程序中,这给了我一个分段错误,因为即时尝试访问玩家结构中不存在的东西,因为玩家永远不会被创建,但在这个例子中,玩家名称显示为(null) )虽然名称是在playercreationMenu函数中给出的。这是为什么?
答案 0 :(得分:3)
count
未初始化。垃圾里的垃圾。
答案 1 :(得分:2)
你写
player p1, p2;
playercreationMenu(&p1, &p2);
但是在构造函数中,你有
void playercreation(player *p, int nr)
{
p = malloc(sizeof(player));
...
}
所以你要将一个malloc()
内存块分配给包含已经分配(在堆栈!)结构地址的局部变量...将调用放到malloc()
和你没事。
在初始化变量或为其赋值之前,您还使用count
变量:
int count;
...
p->name = malloc(sizeof(char) * (count + 1));
所以一,这是未定义的行为,二,你将获得一个相当随机的内存量(这使得可以写出超出其边界 - >另一个未定义的行为),或者如果这将导致分配的内存太多(第三个未定义的行为)。
一行中有三个UB - 确实会崩溃。
答案 2 :(得分:2)
您的代码在以下两行中存在问题:
p=malloc(sizeof(player));
int count;
malloc是没有必要的,因为当你在main()中声明它们时,你已经为堆栈中的玩家结构分配了空间。
您没有初始化计数,这意味着它具有垃圾值。当你用count调用malloc时,你可能会请求任意大量的内存。
答案 3 :(得分:1)
首先,你永远不会像其他人指出的那样初始化count
。这意味着它是一个任意值,因此你不知道你传递给malloc
的是什么。
您也可能不应该使用scanf
,因为如果有人输入超过10个字符,您将溢出缓冲区。我建议改为fgets
。
此外,您首先在堆栈中声明您的玩家,并将指针传递给playercreationMenu
。那样就好。然后你将它们传递给playercreation
,这也很好。在playercreation
中,然后使用从malloc
返回的指针将指针覆盖到播放器。所以你永远不会对你在player
堆栈中分配的原始main
做任何事情。
正如Basile建议的那样,使用-Wall
进行编译以获得更多编译器警告并密切关注它们是个好主意。实际上,我更喜欢-Wall -Wextra -Werror
; -Wall
实际上并未向您发出所有警告,因此-Wextra
会更加有用,-Werror
会将警告变为错误,因此您无法忽略它们。