访问结构的成员时发生分段错误

时间:2019-01-15 20:59:04

标签: c segmentation-fault

当我想使用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成员。

有人有什么想法吗?

1 个答案:

答案 0 :(得分:2)

char msg[2];
bzero(msg, strlen(msg));

好的,因此在这里您尝试计算未初始化的字符串的长度,这是页面错误(和内核漏洞)的典型来源。 strlen不知道您数组的大小,它只是寻找一个零字符并且很可能很快就会退出您的页面。即使程序此时没有崩溃,bzero也会成功,因为它可能写入超出您的访问范围。

请注意,通常用至少两个字符(“ C4”左右)来描述一个单元格,因此scanf将在msg的末尾写一个终止的零字符(同样,可以是甚至没有可用的内存)。增加msg的大小,以便至少可以容纳有效输入(至少三个字符,越多越好)。而且您无需在此处致电strlen;如果要预先清除数组,最简单的方法是正确初始化它:char msg[256] = {'\0'};

接下来,您没有显示NewPlayer()的代码,但是您的结构包含三个指针字段,请仔细检查它们的分配和正确初始化。