Недавно я протестировал ограничение стека на трех устройствах с разными ОС (под лимитом я подразумеваю максимальное количество уровней, которое может иметь стек), и я заметил, что каждый раз, когда я достигаю 2 ^ 16 уровней, это дает мне ошибка переполнения, и когда я ставлю 2 ^ 16-1, он работает правильно.
Итак, мой вопрос - это правда? У стека есть максимальный предел 2 ^ 16-1 по определению или это зависит от ОС?
here i mean by limit the maximum number of levels that can the stack have
какой уровень?Ответы:
Это сильно зависит от операционной системы (и компьютера), и в некоторых ОС у вас есть несколько способов настроить (и даже увеличить) ограничение. Это даже зависит от компилятора (или от конкретной реализации вашего языка программирования), поскольку некоторые компиляторы (включая недавний GCC для некоторого ограниченного вида кода на C) способны оптимизировать некоторые хвостовые вызовы .
(некоторые спецификации языка программирования требуют оптимизации хвостового вызова, например R5RS )
Я не уверен, что ваш вопрос имеет смысл (и, конечно, не ваш 2 16 предел). На моем рабочем столе Linux (Debian / Sid / x86-64, ядро Linux 4.9, 32 ГБ ОЗУ, Intel i5-4690S) у меня может быть стек вызовов до 8 мегабайт (и я мог бы увеличить этот предел, если бы я действительно хотел ).
Многопоточность и ASLR делает ваш вопрос гораздо сложнее . Смотрите, например, pthread_attr_setstack (3) . Читайте также о разделенных стеках (часто используемых реализациями Go ) и о стиле передачи продолжения . Смотрите также этот ответ.
Для чего это стоит, я только что попробовал следующий код C99 (а также C11):
и я смог запустить эту
recur
программу (скомпилированную с GCC 6 asgcc -Wall -O recur.c -o recur
)recur 161000
(намного выше вашего предела в 2 16 ). Сrecur 256000
этим тоже работал. Сrecur 456000
ним разбился (с переполнением стека для уровняx=272057
). У меня нет терпения для других тестов. Попробуйте это на своем компьютере. Не забудьте спросить об оптимизации.Эмпирическое правило (для настольных компьютеров, ноутбуков, планшетов) может заключаться в том, чтобы стек вызовов не превышал одного мегабайта.
Переходя также
-fstack-usage
кgcc
получению следующегоrecur.su
файла (числа в байтах, в соответствии с моей интуицией ограничения стека в 8 Мбайт; не забывайтеmain
фрейм вызова и, что более важно, начальную компоновку стека, установленную ядром при выполнении execve (2). ) ..., для crt0 ):PS. Мой Arduino имеет Atmega328 только с 2 Кбайт оперативной памяти, поэтому, конечно, не может повторить так много. Я предполагаю, что на Arduinos возможно практически несколько сотен фреймов стека.
источник
Размер стека для основного потока процесса Windows задается компоновщиком. Значение по умолчанию составляет 1 МБ, но его можно настроить с помощью переключателя / STACK. Потоки, созданные позже, могут использовать параметр dwStackSize функции CreateThread.
Так что ... если вы тестируете различные ОС Windows, у них у всех одинаковый размер стека по умолчанию, начиная как минимум с NT4.0.
источник