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

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

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

#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;
}

8

Решение

Мои оценки поставил sizeof(Tile) на 8 или больше. Это означает sizeof(Server) составляет не менее 360 * 360 * 8 = 1036800, что составляет 0,99 МБ. Стек, как правило, небольшой, и 1 МБ — это стандартный размер по умолчанию. Вместо этого вы должны разместить плитки в куче, возможно, используя 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]
};
8

Другие решения

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

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

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

5

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

4

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

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

Размер стека по умолчанию составляет 1 МБ. ваш размер структуры = ushort (2 байт) + ulong (4 байт) = 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 ~ 800 МБ

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

    / F801000000

введите описание изображения здесь

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

    / STACK: 801000000

введите описание изображения здесь

Готово!

3 — третье решение — это динамический массив для размещения в куче, а не статический массив, как все уже сказали.

0
По вопросам рекламы [email protected]