Я использую 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;
}
Мои оценки поставил 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]
};
Вы выделяете массив 360 x 360 Tile
объекты в стеке. Это плохая идея с самого начала. Вам выделен очень большой блок памяти в стеке. Стек не предназначен для этого типа использования.
Эта память должна быть статической, если вам нужен только один экземпляр и заранее знать размер, или вы должны выделить его из кучи (используя new
или даже malloc()
).
Рассмотрим наличие конструктора для Server
выделить память, используя new
вместо того, чтобы делать это, как вы это делаете.
Стек имеет ограниченный размер. Если вам нужно держать большой массив, используйте динамическое размещение.
Вы создали тип, который требует ~ 1 МБ стекового пространства на экземпляр, что, очевидно, больше, чем может вместить ваш стек.
Размер стека по умолчанию составляет 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 — третье решение — это динамический массив для размещения в куче, а не статический массив, как все уже сказали.