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

使用Raylib开发扫雷游戏时堆上创建数组致崩溃的问题

扫雷游戏堆数组初始化导致崩溃问题分析

问题描述

使用Raylib开发扫雷游戏时,为支持自定义地图尺寸,在堆上创建bool* map和bool* overlay两个数组表示网格。保留构造函数中的数组初始化循环时程序崩溃,移除则正常运行,崩溃发生在主循环结束阶段。

相关代码

game.h

#pragma once

#include <raylib.h>

class Game
{
    bool* map;
    bool* overlay;
    int width, height;

public:
    Game();
    Game(int _width, int _height, int mines, int seed, int startX, int startY);
    ~Game();
    void tick();
    void draw() const;
};

Game.cpp

Game::Game(int _width, int _height, int mines, int seed, int startX, int startY) 
{
    map = new bool[width*height];
    overlay = new bool[width*height];
    width = _width;
    height = _height;
    for (int i = 0; i < width * height; i++)
        map[i] = false;
    for(int i = 0; i < width*height; i++)
        overlay[i] = true;
    SetRandomSeed(seed);
    for(int i = 0; i < mines; i++)
    {
        int x = GetRandomValue(1, width), y = GetRandomValue(1, height);
        while(map[(x+width*y)-1] || (x == startX && y == startY))
            x = GetRandomValue(1, width), y = GetRandomValue(1, height);
        map[(x+width*y)-1] = true;
    }
}

void Game::draw() const
{
    for(int y = 0; y < height; y++)
        for (int x = 0; x < width; x++)
        {
            if(overlay[width*y+x])
                DrawRectangle(x*10,y*10, 10, 10, (y+x)%2 == 0 ? DARKGRAY : LIGHTGRAY);
        }
}

Main.cpp

#include <raylib.h>

#include "game.h"

int main(void)
{
    InitWindow(800, 450, "raylib [core] example - basic window");
    Game game(24, 24, 5, 0, 0, 0);

    while (!WindowShouldClose())
    {
       // 其他逻辑
       game.draw();
    } // 异常抛出位置

    CloseWindow();

    return 0;
}

异常截图

Visual Studio异常截图

问题根源

构造函数中先执行数组内存分配,再给width和height赋值,此时width*height是未初始化的垃圾值,导致分配的数组大小完全错误。后续初始化循环访问数组时,会出现内存越界,破坏堆内存结构,最终在程序结束析构对象时触发崩溃。

修复方案

调整代码顺序,先给成员变量width和height赋值,再分配数组内存:

Game::Game(int _width, int _height, int mines, int seed, int startX, int startY) 
{
    width = _width;
    height = _height; // 优先初始化成员变量
    map = new bool[width*height];
    overlay = new bool[width*height];
    // 后续初始化循环及逻辑保持不变
    for (int i = 0; i < width * height; i++)
        map[i] = false;
    for(int i = 0; i < width*height; i++)
        overlay[i] = true;
    SetRandomSeed(seed);
    for(int i = 0; i < mines; i++)
    {
        int x = GetRandomValue(1, width), y = GetRandomValue(1, height);
        while(map[(x+width*y)-1] || (x == startX && y == startY))
            x = GetRandomValue(1, width), y = GetRandomValue(1, height);
        map[(x+width*y)-1] = true;
    }
}

额外建议

  • 避免使用裸指针管理堆内存,改用std::unique_ptr<bool[]>自动释放内存,防止内存泄漏:
    #include <memory>
    class Game {
        std::unique_ptr<bool[]> map;
        std::unique_ptr<bool[]> overlay;
        // ...
    };
    // 构造函数中直接初始化:
    map = std::make_unique<bool[]>(width*height);
    
  • 或者使用std::vector<bool>,它会自动处理内存分配和释放,代码更简洁安全:
    #include <vector>
    class Game {
        std::vector<bool> map;
        std::vector<bool> overlay;
        // ...
    };
    // 构造函数中:
    map.resize(width*height, false);
    overlay.resize(width*height, true);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 10:04:53