我正在尝试用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
答案 0 :(得分:5)
可能是堆栈溢出(真的!),虽然我不确定。
Game game;
中声明main()
。这意味着所有102400字节的game
都在堆栈上。printGame
和hasGameEnded
都需要Game game
,而不是Game * game
。也就是说,他们正在获取Game
的副本,而不是现有Game
的指针。因此,无论何时调用其中一个,都会在堆栈上转储另外102400个字节。 我猜这个对printGame
的调用正在以一种导致hasGameEnded
调用问题的方式破坏堆栈。
我所知道的最简单的修复(没有进入动态内存分配,这可能是更好的长期)是:
Game game;
移到main()
之外,例如移至int main(...)
上方的行。这样它就会在数据段中,而不是在堆栈上。更改printGame
和hasGameEnded
以Game *
:
void printGame(Game * game) {
printf("Game -> %p (%d)\n", game, sizeof(Game));
fflush(stdout);
}
int hasGameEnded(Game * game) {
printGame(game);
return 0;
}
这应该让你前进。
答案 1 :(得分: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()
。
另请注意,proper format specifier for sizeof
includes a z
modifier.我冒昧地将u
设为无符号,因为大小不能为负。