Создание статического массива в куче? - PullRequest
2 голосов
/ 01 февраля 2011

Мне нужно создать очень большой массив. Допустим, 50 мегабайт.

Можно ли создать его как обычный статический массив? Будет ли компилятор помещать его в стек (возможно, вызывая переполнение стека), или он будет достаточно умен, чтобы поместить его в кучу?

Если нет способа сделать это, есть ли простой способ сделать это с помощью malloc или «new» при запуске программы, но автоматически освободить его при завершении программы?

Ответы [ 5 ]

3 голосов
/ 01 февраля 2011

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

Кроме того, когда программа завершается, все автоматически освобождается.

2 голосов
/ 01 февраля 2011

По моему опыту, лучше выделить такой большой массив в куче (таким образом, через new) - я видел дамп ядра программы в системе unix после выделения 2 МБ в стеке Если вы хотите автоматическое удаление, вы можете использовать умный указатель (скажем, boost :: scoped_array). Но, поскольку вы упоминаете «автоматическое удаление, когда программа заканчивается», вам на самом деле ничего не нужно делать - операционная система освободит всю память вашего процесса, когда она завершится.

В любом случае, вы действительно должны использовать std :: vector вместо необработанного массива.

2 голосов
/ 01 февраля 2011

Простой способ сделать это с помощью std :: vector

std::vector   data;
data.reserve(<Number of Elements);

или потенциально std :: deque (в зависимости от вашего использования).

Будет ли компилятор помещать его в стек (возможно, вызывая переполнение стека), или он будет достаточно умен, чтобы поместить его в кучу?

Переполнение стека - это когда теоретический стек и теоретическая куча сталкиваются и смешиваются. Если стек собирался переполнить, то и куча не работает.

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

std :: vector делает это (вероятно). Он имеет небольшое присутствие локального объекта, но основная полезная нагрузка (обычно) реализована в виде динамического распределения кучи.

1 голос
/ 01 февраля 2011

Если вы распределите его статически, он будет распределен статически. В типичном случае в исполняемом файле будет какая-то запись, указывающая, что конкретная переменная должна быть инициализированным нулем блоком размера N. Загрузчик обычно соблюдает это, точно так же, как он выделяет место для кода программы такой (например, он будет выделять адресное пространство, но довольно часто не фактическая память для его резервного копирования до тех пор, пока вы / не будете фактически читать / записывать эту память).

0 голосов
/ 01 февраля 2011

50 мегабайт не слишком много по сегодняшним меркам.

Вы можете выделить его в начале вашей программы, используя новый оператор C ++, и освободить его с помощью delete [] в конце (или в начале / конце определенного раздела программы).

Если этот массив представляет, например, какой-то файл, который нужно загрузить, лучше, конечно, выделить его, когда файл загружен в память. Оптимально, вы можете отобразить только часть файла в памяти (например, 1 МБ, 2 МБ или другой логический «блок», который вы хотите использовать) (см. MapViewOfFile в Windows и mmap в системах UNIX). Таким образом, вы можете загружать очень большие файлы, не исчерпывая свою виртуальную память.

...