Предел массива стека C++?

Я запускаю некоторый код, который может указывать, что я не понимаю разницу между кучей и стеком. Ниже приведен пример кода, в котором я либо объявляю массив в стеке, либо кучу 1234567 элементов. Оба работают.

int main(int argc, char** argv){

  int N = 1234567;

  int A[N];

  //int* A = new int[N];

}

Но если мы возьмем N равным 12345678, я получу ошибку сегмента с int A[N], тогда как объявление кучи все еще работает нормально. (Я использую g++ O3 -std= C++0x, если это имеет значение). Что это за безумие? Есть ли в стеке (довольно маленький) предел размера массива?

2 ответа

Решение

Куча растет динамически с выделением через malloc и co. Стек увеличивается с каждым вызовом функции, выполняемым в ходе работы программы. Адрес возврата, аргументы, локальные переменные обычно хранятся в стеке (за исключением того, что в некоторых архитектурах процессоров несколько из них хранятся вместо этого в регистрах). Также возможно (но не распространено) динамическое выделение стекового пространства.

Куча и стек конкурируют за использование одной и той же памяти. Вы можете думать о том, что один растет слева направо, а другой растет справа налево. Существует вероятность того, что, если их не остановить, они могут столкнуться. Стек, как правило, сдерживается от выхода за пределы определенной границы. Это относительно мало, поскольку ожидается, что он будет использовать только несколько байтов для большинства вызовов, и будет использоваться только несколько уровней стека. Предел небольшой, но достаточный для большинства задач. Вы можете расширить этот лимит, изменив настройки сборки (но не для бинарных файлов Linux ELF) или вызвав setrlimit. ОС также может устанавливать ограничение, которое вы можете изменить. Могут быть мягкие и жесткие ограничения (http://www.nics.tennessee.edu/node/327).

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

http://en.wikipedia.org/wiki/Call_stack

Это связано с тем, что размер стека намного меньше размера кучи. Куча может занимать всю память, доступную программе. По умолчанию VC++ компилирует стек размером 1 МБ. Стек обеспечивает лучшую производительность, но предназначен для меньших объемов данных. Как правило, он не используется для больших структур данных. Вот почему функции, принимающие списки / массивы / словари /ect в C++, обычно принимают указатель или ссылку на эту структуру. Параметры, передаваемые по значению, копируются в стек, и передача таких структур часто приводит к сбою программ.

В вашем примере вы используете N intх, ан int 4 байта. Это делает размер A[N] ~4,7 МБ, намного больше, чем размер вашего стека.

Другие вопросы по тегам