2017-03-27 91 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