将结构从 main() 传递到辅助函数时出现段错误
Segfault when passing structure from main() to worker functions
我正在尝试用 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
这可能是堆栈溢出(真的!),虽然我不确定。
- 您正在
main()
中声明 Game game;
。这意味着 game
的所有 102400 字节都在堆栈中。
printGame
和 hasGameEnded
都采用 Game game
,而不是 Game * game
。也就是说,他们得到的是 Game
的 copy,而不是现有 Game
的 pointer。因此,无论何时调用其中任何一个,都会在堆栈上转储另外 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;
}
这应该会让你继续前进。
您可能 运行 堆栈不足 space。
C 是按值传递。所以这段代码
int hasGameEnded(Game game)
创建整个 struct {} Game
的 副本 ,很可能在堆栈上。
如果以下代码有效,则您 运行 出栈 space:
...
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
无符号,因为大小不能为负数。
我正在尝试用 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
这可能是堆栈溢出(真的!),虽然我不确定。
- 您正在
main()
中声明Game game;
。这意味着game
的所有 102400 字节都在堆栈中。 printGame
和hasGameEnded
都采用Game game
,而不是Game * game
。也就是说,他们得到的是Game
的 copy,而不是现有Game
的 pointer。因此,无论何时调用其中任何一个,都会在堆栈上转储另外 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; }
这应该会让你继续前进。
您可能 运行 堆栈不足 space。
C 是按值传递。所以这段代码
int hasGameEnded(Game game)
创建整个 struct {} Game
的 副本 ,很可能在堆栈上。
如果以下代码有效,则您 运行 出栈 space:
...
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
无符号,因为大小不能为负数。