Предел выделения стека для программ на 32-битной машине Linux
В C++ сколько может расти сегмент стека до того, как компилятор сдастся и скажет, что не может выделить больше памяти для стека.
Использование gcc на 32-битной машине linux (fedora).
3 ответа
Под UNIX, если вы используете bash, запустите
$ ulimit -a
в нем будут перечислены различные ограничения, включая размер стека. Мой 8192 КБ. Вы можете использовать ulimit, чтобы изменить пределы.
Также вы можете использовать функцию ulimit() для установки различных ограничений в вашей программе.
$ man 3 ulimit
Под Windows смотрите StackReserveSize и StackCommitSize
На практике адреса стеков начинаются с высоких адресов (на 32-разрядной платформе, близких к пределу в 3 ГБ) и уменьшаются, а выделение памяти начинается с низких адресов. Это позволяет стеку и памяти расти, пока вся память не будет исчерпана.
На моем 32-битном Linux, его 8192K байтов. Так должно быть и на твоей машине.
$ uname -a
Linux TomsterInc 2.6.28-14-generic #46-Ubuntu SMP Wed Jul 8 07:21:34 UTC 2009 i686 GNU/Linux
$ ulimit -s
8192
Windows (и я думаю, что Linux) работают в предположении модели большого стека, то есть существует один стек (на поток), пространство которого предварительно выделено до запуска потока. Я подозреваю, что ОС просто назначает пространство виртуальной памяти предварительно выделенного размера для этой области стека и добавляет страницы реальной памяти внизу, когда конец стека продвигается за пределы границы страницы, пока не будет достигнут верхний предел ("ulimit").ck
Так как ОС часто размещают стеки далеко от другой структуры, при достижении ulimit вполне возможно, что ОС сможет расширить стек, если при переполнении рядом со стеком не появится ничего другого. В общем, если вы строите программный комплекс, достаточный для переполнения стека, вы, вероятно, выделяете память динамически, и нет гарантии, что область рядом со стеком не была выделена. Если такая память выделена, конечно, ОС не может расширить стек там, где она есть.
Это означает, что приложение не может рассчитывать на расширение стека ОС автоматически. По сути, стек не может расти.
Теоретически, приложение, исчерпавшее свой стек, может запустить новый поток с большим стеком, скопировать существующий стек и продолжить, но с практической точки зрения я сомневаюсь, что это можно сделать, если только по указателям на стек локальных переменных потребуется настройка, а компиляторы C/C++ не позволят найти такие указатели и настроить их. Следствие: ulimit должен быть объявлен до запуска программы, и после превышения программа умирает.
Если кто-то хочет, чтобы стек мог произвольно расширяться, лучше переключиться на язык, который использует выделенные в куче записи активации. Тогда вы просто не закончите, пока ваше адресное пространство не израсходовано. 32 или 64-битные виртуальные пространства гарантируют, что вы можете выполнить много рекурсии с помощью этой техники.
У нас есть язык параллельного программирования под названием PARLANSE, который распределяет кучу, чтобы позволить тысячам параллельных вычислительных гранул (на практике) произвольно повторяться таким образом.