将结构从main()传递给worker函数时的Segfault

Fre*_*dan 2 c struct pass-by-value segmentation-fault pass-by-pointer

我正在尝试用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;
}
Run Code Online (Sandbox Code Playgroud)

我尝试用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
Run Code Online (Sandbox Code Playgroud)

cxw*_*cxw 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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

那会让你前进.