You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含内部数组的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 **),但你尝试的分配方式要么类型不匹配,要么没有正确构建二维数组的指针结构**:

  1. 先明确二级指针的二维数组结构:
    snakeEntity **board 需要先分配一个指针数组(每个元素是指向一行的指针),然后为每个指针分配对应列数的snakeEntity数组。你之前的方式2有一个错误:分配指针数组时,应该用sizeof(snakeEntity *)而不是sizeof(snakeEntity),因为数组里存的是指针,不是枚举值。

  2. 正确的内存分配实现:

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;
}
  1. 额外注意事项:
    • 所有malloc调用必须检查返回值是否为NULL,避免空指针访问。
    • 当某一行分配失败时,要释放之前已经分配的所有内存,防止内存泄漏。
    • 中间未初始化的格子要设置为EMPTY,避免未定义行为。
    • C标准中不需要强制转换malloc的返回值,强制转换反而可能隐藏类型错误。

内容的提问来源于stack exchange,提问作者Blundergat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:58:11