C++ 3D 数组到 1D 导致堆缓冲区溢出

标签 c++ arrays buffer-overflow

我想举一个最小的例子。如果提供的代码还不够,请告诉我您还需要什么。这不是什么 super secret ;)

考虑以下两个实现:

使用 3d 数组:

.h

class Grid
{
    public:
        Grid();

        uint8_t get(int x, int y, int z);
        void set(int x, int y, int z, uint8_t value);

    private:
        uint8_t blocks[Chunk::width][Chunk::height][Chunk::depth];
};

.cpp

Grid::Grid()
{
    memset(blocks, 0, sizeof(blocks));
}

uint8_t Grid::get(int x, int y, int z)
{
    return blocks[x][y][z];
}

void Grid::set(int x, int y, int z, uint8_t value)
{
    blocks[x][y][z] = value;
}

现在是一维数组:

.h

class Grid
{
    public:
        Grid();

        uint8_t get(int x, int y, int z);
        void set(int x, int y, int z, uint8_t value);

    private:
        uint8_t blocks[Chunk::width * Chunk::height * Chunk::depth];
        int to1D(int x, int y, int z) { return x + (y * Chunk::width) + (z * Chunk::width * Chunk::height); }
};

.cpp

Grid::Grid()
{
    memset(blocks, 0, sizeof(blocks));
}

uint8_t Grid::get(int x, int y, int z)
{
    return this->blocks[x + (y * Chunk::width) + (z * Chunk::width * Chunk::height)];
}

void Grid::set(int x, int y, int z, uint8_t value)
{
    this->blocks[x + (y * Chunk::width) + (z * Chunk::width * Chunk::height)] = value;
}

现在有了 3D 版本,一切都像魅力一样,而对于相同的整体尺寸我得到了

SUMMARY: AddressSanitizer: heap-buffer-overflow src/Grid.cpp:16 in Grid::get(int, int, int)

我真的很想知道为什么会这样。两种实现都包含 uint8_t...我似乎看不到/无法理解的 3d 数组版本中正在进行什么优化?

(是的,这是我的世界体素引擎实验;))

最佳答案

如果您正在为游戏构建环境,我猜您会遇到内存分配问题。假设您正在运行的游戏需要 50 MB 内存。从任何地方获取 50 MB 都不是什么大问题。但是试图获得 50 MB 的连续内存是 waaaaaayyy 更困难。现在大多数操作系统都使用分页系统来跟踪已分配和未分配的内存。这里有更多信息:https://en.wikipedia.org/wiki/Paging

3D 数组基本上是指向指针数组的指针,其中每个指针都指向另一个指针数组。这些指针中的每一个都包含一个有限的内存块来与之交互。所以在这种情况下,操作系统可以给你 5,000 个 50 KB 的内存块,指针可以将所有这些内存保存在不同的地方。

关于C++ 3D 数组到 1D 导致堆缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43056536/

相关文章:

c++ - 如何清除 C++ 中的动态数组以及堆栈中有多少?

c - 我如何绕过返回地址覆盖而不是重定向控制流?

c++ - 如何构建接收引用参数的基类?

c++ - 错误 : Thread 1: EXC_BAD_ACCESS (code=1, 地址=0x0)

c++ - 如何将 char 缓冲区的一部分复制到 std::string?

java - 即使数据集更改为另一个值,哈希值也不会更改

c++ - 在对话框 (wxDialog) 中安装一个大网格 (wxGrid)

javascript - 我如何从中创建 Bootstrap 行? ( react JS)

将指针更改为指向堆栈地址而不是堆地址

c - 利用缓冲区溢出的问题