不在另一个函数中访问指向struct的指针作为参数

时间:2012-11-08 18:08:39

标签: c pointers

我有这个示例文件

example.c

#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函数中给出的。这是为什么?

4 个答案:

答案 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会将警告变为错误,因此您无法忽略它们。