含内部数组的snakeGame结构体创建引发程序挂起与UB问题求助
蛇游戏结构体创建时的未定义行为问题
我编写的C语言代码中,createSnakeGame函数用于创建snakeGame结构体,但程序会挂起并在随机时间后异常退出,始终无法执行到main函数中的printf("Success")语句。
枚举定义
typedef enum { SNAKE_HORIZONTAL, SNAKE_VERTICAL, SNAKE_UP_RIGHT, SNAKE_UP_LEFT, SNAKE_DOWN_RIGHT, SNAKE_DOWN_LEFT, FOOD, BORDER, EMPTY } snakeEntity;
结构体定义
typedef struct { snakeEntity ** board; int rows; int columns; } snakeGame;
createSnakeGame函数
snakeGame * createSnakeGame() { int row = 10; int col = 10; snakeGame * game = (snakeGame *) malloc(sizeof(snakeGame)); game->rows = row; game->columns = col; for (int i = 0; i < row; i++) { if (i == 0 || i == row - 1) { for (int j = 0; j < col; j++) { game->board[i][j] = BORDER; } } else { game->board[i][0] = BORDER; game->board[i][col - 1] = BORDER; } } return game; }
main函数
int main() { snakeGame * game = createSnakeGame(); printf("Success"); return 0; }
我尝试了多种内存分配方式,但仍存在未定义行为(UB):
- 方式1:为结构体额外分配数组内存
// 为结构体额外分配数组内存 snakeGame * game = (snakeGame *) malloc(sizeof(snakeGame) + (row * col * sizeof(snakeEntity)));
- 方式2:为每行单独分配对应列数的内存
// 为每行单独分配对应列数的内存 game->board = (snakeEntity **) malloc(row * sizeof(snakeEntity)); for (int i = 0; i < row; i++) { game->board[i] = (snakeEntity *) malloc(col * sizeof(snakeEntity)); }
- 方式3:单独初始化board
// 单独初始化board snakeGame * game = (snakeGame *) malloc(sizeof(snakeGame)); snakeEntity ** board = (snakeEntity **) malloc(row * col * sizeof(snakeEntity)); game->board = board;
问题根源与解决建议
问题核心是**snakeGame中的board是二级指针(snakeEntity **),但你尝试的分配方式要么类型不匹配,要么没有正确构建二维数组的指针结构**:
先明确二级指针的二维数组结构:
snakeEntity **board需要先分配一个指针数组(每个元素是指向一行的指针),然后为每个指针分配对应列数的snakeEntity数组。你之前的方式2有一个错误:分配指针数组时,应该用sizeof(snakeEntity *)而不是sizeof(snakeEntity),因为数组里存的是指针,不是枚举值。正确的内存分配实现:
snakeGame * createSnakeGame() { int row = 10; int col = 10; snakeGame * game = malloc(sizeof(snakeGame)); if (!game) { // 必须检查malloc是否成功 return NULL; } game->rows = row; game->columns = col; // 第一步:分配指针数组,每个元素是指向一行的snakeEntity* game->board = malloc(row * sizeof(snakeEntity *)); if (!game->board) { free(game); return NULL; } // 第二步:为每一行分配列数的snakeEntity内存 for (int i = 0; i < row; i++) { game->board[i] = malloc(col * sizeof(snakeEntity)); if (!game->board[i]) { // 分配失败时回滚已分配内存,避免泄漏 for (int j = 0; j < i; j++) { free(game->board[j]); } free(game->board); free(game); return NULL; } // 初始化当前行内容 if (i == 0 || i == row - 1) { for (int j = 0; j < col; j++) { game->board[i][j] = BORDER; } } else { game->board[i][0] = BORDER; game->board[i][col - 1] = BORDER; // 中间格子初始化为EMPTY,避免未定义的垃圾值 for (int j = 1; j < col - 1; j++) { game->board[i][j] = EMPTY; } } } return game; }
- 额外注意事项:
- 所有
malloc调用必须检查返回值是否为NULL,避免空指针访问。 - 当某一行分配失败时,要释放之前已经分配的所有内存,防止内存泄漏。
- 中间未初始化的格子要设置为
EMPTY,避免未定义行为。 - C标准中不需要强制转换
malloc的返回值,强制转换反而可能隐藏类型错误。
- 所有
内容的提问来源于stack exchange,提问作者Blundergat
相关产品推荐
相关产品推荐

