当我想使用C编程语言访问或修改struct成员的值时,会发生segmentation fault
。
我实际上用C语言编写了一个战舰网络游戏(这是一个学生项目)。我有一个名为Player
的结构:
enum state{PLAYING = 0, WINNER = 1, LOOSER = 2};
enum action{ATTACK = 1, WAIT = 0, NOTHING = -1};
typedef struct Player Player;
struct Player
{
enum action action;
enum state state;
char name[25];
int isFirstPlayer;
Client* client;
Server* server;
Boards* boards;
};
主要功能。
int main(int argc, char *argv[])
{
if(argc < 2)
{
errorUsage();
}
// Initialise player
Player player = newPlayer();
// I removed the network initialization here.
// play game
play_game(&player);
}
segmentation fault
出现在函数play_game(Player* p)
中:
void attack(Player* p)
{
char msg[2];
bzero(msg, strlen(msg));
printf("Where do you want to fire?");
scanf("%s", msg);
while(verifyEntryAttack(msg) != 1)
{
printf("ERROR Entry:\nFormat = A4, C9, ...\nColumns = A B C D E F G H I J\nRows = 0 1 2 3 4 5 6 7 8 9\n");
printf("please try again: ");
scanf("%s", msg);
}
sendData(p, msg);
Box my_attack_box;
my_attack_box.abs = msg[0];
my_attack_box.ord = msg[1]-'0';
updateMarkBoard(p, my_attack_box);
}
void receiveAttack(Player* p)
{
char received_attack[2];
receiveData(p, received_attack);
printf("I have received the attack: %s\n", received_attack);
Box my_attack_box;
my_attack_box.abs = received_attack[0];
my_attack_box.ord = received_attack[1]-'0';
endureAttack(my_attack_box, p);
}
void play_game(Player* p)
{
while(p->state == PLAYING){
printPlayer(p); //print the game boards.
if(p->action == ATTACK){
printf("Your turn to attack.\n");
attack(p); //attack the ennemy
printf("end of attack turn.\n");
} else if(p->action == WAIT){
printf("wait for an attack...\n");
receiveAttack(p); //receive the attack from the ennemy.
printf("end of waiting turn.\n");
}
if(p->action == WAIT){
p->action = ATTACK;
}
else{
p->action = WAIT;
}
}
}
在while循环中转一圈后,程序将显示“分段错误”。我的测试表明,这是问题所在的p->action
。
请参阅下面显示问题的程序输出:outputs screenshot。
完整的代码可在此处找到:GitLab repo link。
就像我的程序无法访问播放器的action
成员。
有人有什么想法吗?
答案 0 :(得分:2)
char msg[2];
bzero(msg, strlen(msg));
好的,因此在这里您尝试计算未初始化的字符串的长度,这是页面错误(和内核漏洞)的典型来源。 strlen
不知道您数组的大小,它只是寻找一个零字符并且很可能很快就会退出您的页面。即使程序此时没有崩溃,bzero
也会成功,因为它可能写入超出您的访问范围。
请注意,通常用至少两个字符(“ C4”左右)来描述一个单元格,因此scanf
将在msg
的末尾写一个终止的零字符(同样,可以是甚至没有可用的内存)。增加msg
的大小,以便至少可以容纳有效输入(至少三个字符,越多越好)。而且您无需在此处致电strlen
;如果要预先清除数组,最简单的方法是正确初始化它:char msg[256] = {'\0'};
。
接下来,您没有显示NewPlayer()
的代码,但是您的结构包含三个指针字段,请仔细检查它们的分配和正确初始化。