Переполнение стека C++ Visual Studio с 2D-массивом

Я использую Visual Studio 2010 Win 8. У меня есть класс, где я делаю 2Д массив для хранения игровых данных для игры.

создайте пустое консольное приложение и сделайте main.cpp и добавьте этот код. Использование 360 для MAP_SIZE вызывает переполнение стека с помощью 359 не делает. С чего бы это? Я ищу массив гораздо большего размера. Я бы хотел что - то вроде 2000-10,000 в идеале.

#define MAP_SIZE 360

typedef unsigned short ushort;
typedef unsigned long ulong;

struct Tile
{
    ushort baseLayerTileID;
    ulong ownerID;
};

class Server
{
private:
    Tile _map[MAP_SIZE][MAP_SIZE];
};


int main()
{
    Server s;

    return 0;
}

5 ответов


мои оценки ставить sizeof(Tile) на 8 или больше. Это значит sizeof(Server) по крайней мере 360*360*8 = 1036800, которая составляет 0,99 МБ. Стек обычно небольшой, и 1MB является общим размером по умолчанию. Вместо этого вы должны выделить плитки в куче, возможно, используя std::vector.

class Server
{
public:
    Server() : _map(MAP_SIZE * MAP_SIZE) {}
private:
    std::vector<Tile> _map; // position [i][j] is at [i*MAP_SIZE+j]
};

вы выделяете массив 360 x 360 Tile объекты на стеке. Это плохая идея с самого начала. Вам выделяется очень большой блок памяти в стеке. Стек не предназначен для такого типа использования.

эта память должна быть статической, если вам нужен только один экземпляр и вы заранее знаете размер, или вы должны выделить ее из кучи (используя new или даже malloc()).

рассмотреть конструктор Server выделить память используя new вместо того, чтобы делать это так, как вы это делаете.


стек имеет ограниченный размер. Если вам нужно держать большой массив, используйте динамическое распределение.


вы создали тип, который требует ~1 МБ пространства стека на экземпляр, который, по-видимому, больше, чем может вместить ваш стек.

  • переносная опция состоит в том, чтобы перейти от фиксированного массива к динамически выделенному или векторному типу.
  • непереносимая опция-увеличить размер стека в вашем приложении (что, в свою очередь, увеличивает размер стека для всех потоков)

размер стека по умолчанию равен 1 Мб. ваш размер структуры = ushort (2bytes) + ulong (4byte)= 6 байт, которые компилятор преобразует в 8 байт для выравнивания структуры . так что ... 8*360*360 =1036800 байт, незначительно выше 1 МБ

есть 3 решения:

1-выравнивание остановки силы:

 #pragma pack(push)  /* push current alignment to stack */
 #pragma pack(1)     /* set alignment to 1 byte boundary */
 struct Tile
 {
   ushort baseLayerTileID;
   ulong ownerID;
 };
 #pragma pack(pop)   /* restore original alignment from stack */

Это позволит для максимального MAP_SIZE= sqrt (1024*1024/6)=418 ,так что это позволяет для большего размера карты, но не размер вы хотите

2-можно изменить visual studio параметры, позволяющие компилятору и компоновщику использовать более 1 МБ в стеке: вам нужно изменить его, чтобы он был больше максимального размера карты, который вам нужен 8*10000*10000 ~800MB

  • щелкните правой кнопкой мыши проект и выберите Свойства из меню .
  • перейдите в свойства конфигурации - >C / C++-> Командная строка, добавьте этот параметр:

    / F801000000

enter image description here

  • перейти к конфигурации свойства->Компоновщик->командная строка, добавьте этот параметр

    / стек: 801000000

enter image description here

готово!

3-третье решение-динамический массив для распределения по куче, а не статический массив , как все сказали.