2

我正在尝试用 C 编写一个简单的游戏,但我得到了一个 SEGFAULT,但不知道为什么!

这是程序的代码:

#include <stdio.h>
#include <string.h>

#define MAX_PLYS_PER_GAME (1024)
#define MAX_LEN (100)

typedef struct {
   char positionHistory[MAX_PLYS_PER_GAME][MAX_LEN];
} Game;

void getInitialGame(Game * game) {
    memset(game->positionHistory, 0, MAX_PLYS_PER_GAME*MAX_LEN*sizeof(char));
}

void printGame(Game game) {
    printf("Game -> %p (%d)\n", &game, sizeof(game));
    fflush(stdout);
}

int hasGameEnded(Game game) {
    printGame(game);
    return 0;
}

int main(int argc, char *argv[]) {
    Game game;
    getInitialGame(&game);

    if (hasGameEnded(game))
        return -1;

    return 0;
}

我尝试使用 gdb 进行调试,但结果并没有让我走得太远:

C:\Users\test>gdb test.exe
GNU gdb 5.1.1 (mingw experimental)
<snip>
This GDB was configured as "mingw32"...
(gdb) run
Starting program: C:\Users\test/test.exe

Program received signal SIGSEGV, Segmentation fault.
0x00401368 in main (argc=1, argv=0x341c88) at fast-chess-bug.c:29
29              if (hasGameEnded(game))
(gdb) bt
#0  0x00401368 in main (argc=1, argv=0x341c88) at fast-chess-bug.c:29
4

2 回答 2

5

这可能是堆栈溢出(真的!),虽然我不确定。

  1. Game game;main(). 这意味着所有 102400 字节game都在堆栈上。
  2. 两者都printGamehasGameEnded一个Game game,而不是一个Game * game。也就是说,他们得到的是 的副本,而Game不是指向现有的Game. 因此,无论何时调用任何一个,您都会在堆栈上转储另外 102400 个字节。

我猜对的调用printGame正在以一种导致hasGameEnded调用问题的方式破坏堆栈。

我所知道的最简单的解决方法(不涉及动态内存分配,从长远来看可能更好)是:

  1. 移到Game game;之外main(),例如,移到 上面的行int main(...)。这样它将在数据段中而不是在堆栈中。
  2. 改变printGamehasGameEnded采取Game *

    void printGame(Game * game) {
        printf("Game -> %p (%d)\n", game, sizeof(Game));
        fflush(stdout);
    }
    
    int hasGameEnded(Game * game) {
        printGame(game);
        return 0;
    }
    

这应该让你继续前进。

于 2016-10-17T19:41:11.653 回答
2

您可能会用完堆栈空间。

C 是按值传递。所以这段代码

int hasGameEnded(Game game)

创建整个的副本struct {} Game,很可能在堆栈上。

如果以下代码有效,则说明您的堆栈空间不足:

...

void printGame(Game *game) {
    printf("Game -> %p (%zu)\n", game, sizeof(*game));
    fflush(stdout);
}

int hasGameEnded(Game *game) {
    printGame(game);
    return 0;
}

int main(int argc, char *argv[]) {
    Game game;
    getInitialGame(&game);

    if (hasGameEnded(&game))
        return -1;

    return 0;
}

仔细注意变化。hasGameEnded它现在只传递结构的地址,而不是将整个结构传递给 。该更改沿调用堆栈向下流动,最终导致对printGame().

另请注意,正确的格式说明符sizeof包含z修饰符。 我冒昧地将其u设为无符号,因为大小不能为负数。

于 2016-10-17T19:43:59.643 回答