2017-03-27 55 views
1

我想举一个最简单的例子。如果提供的代码不够,请告诉我你还需要什么。这没有什么超级秘密;)C++ 3D数组到1D会导致堆缓冲区溢出

考虑以下两种实现方式:

使用三维数组:

.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版的一切工作就像一个魅力,同时为相同的整体尺寸我得到一个

摘要: AddressSanitizer:堆缓冲区溢出src/Grid.cpp:16在Grid :: get(int,int,int)中

我真的很想知道为什么。两种实现都支持uint8_t s ...在3D数组版本中进行的优化是什么,我似乎无法看到/掌握?

(是的,这是一个minecrafty素引擎实验;))

+0

宽度,高度和深度的值是多大? – Ronin

+0

在@Ronin上跟进,你的代码崩溃的小值x/y/z? – siavashk

+0

你从来没有说过你要调用'Grid :: get'的值。 – PaulMcKenzie

回答

0

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

3D数组基本上是指向指向数组的指针,每个指针指向另一个指针数组。并且每个指针都包含一个有限的内存块来进行交互。所以在这种情况下,操作系统可以为您提供5,000个50 KB的内存块,指针可以将这些内存保存在不同的地方。

+0

我不认为堆内存可以提供50MB,但为什么需要连续的内存?! – Zich

+0

我刚刚在那里扔了一个号码。但基本上他将3D数组中的所有信息存储到一维数组中。一维数组通常被分配一个连续数量的内存,这个内存是在声明时计算的。 – Ronin