Определяет ли стандарт C поведение при переполнении стека?

Существует ли определенное поведение для обработки переполнения стека?

Помимо завершения процесса, не похоже, что можно многое сделать. Мне просто интересно, может ли кто-нибудь знать, что об этом говорит стандарт C.


person Community    schedule 15.03.2009    source источник


Ответы (10)


Стандарт не требует использования стека и ничего не говорит о переполнении стека.

person Community    schedule 15.03.2009

Стандарт C99 не определяет стек; в нем абстрактно обсуждается автоматическое или выделенное хранилище, тогда как непрерывный стек с обнаружением переполнения — это только один из механизмов реализации автоматического хранения.

Раздел 7.14 стандарта определяет SIGSEGV как сигнал, возникающий при "недопустимом доступе к хранилищу". Реализации C не обязаны генерировать какие-либо сигналы, но реализации, использующие непрерывный стек фиксированного размера*, обычно сигнализируют SIGSEGV при обнаружении переполнения стека.

Вы можете зарегистрировать функцию обработчика сигнала для SIGSEGV, но она не может вернуться — "[i]f и когда функция возвращает значение, если значение sig равно SIGFPE, SIGILL, SIGSEGV или любому другому значению, определяемому реализацией соответствующее вычислительному исключению, поведение[u]r не определено".

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

person Pete Kirkham    schedule 15.03.2009

Стандарт C даже не определяет стек, поэтому он, конечно, не определяет, что происходит, когда стек переполняется.

person Rob Kennedy    schedule 15.03.2009

Ответы здесь верны, утверждая, что это не имеет ничего общего со стандартом c, но ваше утверждение о том, что «помимо завершения процесса, не похоже, что можно многое сделать», не является - как правило - истинный.

На самом деле, в большинстве систем с управлением виртуальной памятью и пейджингом по запросу выделенный стек довольно мал (обычно на 4 КБ больше, чем используется в настоящее время) и часто переполняется (что генерирует прерывание по ошибке страницы), и ОС просто добавляет еще одну страницу памяти. памяти в стек для потока.

Ограничение стека - обычно - 1 МБ - это просто довольно произвольная цифра, выбранная для защиты от неконтролируемых программ, и, как правило, не является абсолютным пределом (хотя это было на некоторых моделях памяти с процессорами Intel IIRC). Как правило, не имеет смысла выделять 1 МБ физической памяти для каждого потока.

person Dipstick    schedule 15.03.2009

Согласно некоторым ответам на этот вопрос, в стандартах C даже ничего не говорится о существовании стека, не говоря уже о переполнении стека.

person Alnitak    schedule 15.03.2009

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

person Jack Edmonds    schedule 15.03.2009

Это зависит от операционной системы. Однако многие операционные системы позволяют перезаписывать размер стека по умолчанию. Например, в Windows вы можете использовать этот флаг компоновщика, чтобы увеличить размер стека с 1 МБ до более высокого значения.

person Reed Copsey    schedule 15.03.2009

Как уже упоминалось, в стандарте ничего не говорится о стеке.

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

::римшот::

person Michael Burr    schedule 15.03.2009

Стандарт C в этом отношении противоречив. Рассмотрим следующую программу:

void foo(uintptr_t n)
{
    int a;
    printf("%p\n", (void *)&a);
    if (n+1) foo(n+1);
}
int main()
{
    int a;
    printf("%p\n", (void *)&a);
    foo(0);
}

Эта программа полностью соответствует требованиям и не нарушает ни одного из минимальных ограничений перевода, и, как уже говорили другие, в языке стандарта нет ничего об ограничениях/переполнении стека. Однако он создает UINTPTR_MAX+2 объекта a (на каждом уровне вызова), все времена жизни которых перекрываются, каждый с разными адресами. Это невозможно с помощью простого подсчета аргументов.

person R.. GitHub STOP HELPING ICE    schedule 26.02.2015

В некоторых системах обеспечение любой предсказуемой выгоды после переполнения стека привело бы к значительным накладным расходам на каждый вызов функции; таким образом, стандарт вполне обоснованно расценивает переполнение стека как Undefined Behavior. Это вполне уместно, если цель состоит в том, чтобы максимизировать эффективность, с которой реализация может запускать законные программы.

Стандарт также не требует, чтобы в системе было достаточно стека для поддержки любой нетривиальной глубины вызовов функций. Учитывая, что некоторые полезные программы (особенно в мире встраиваемых систем) могут обойтись менее чем 16 байтами стека и могут не обязательно иметь возможность выделять больше ОЗУ, чем это, требование большого стека нарушит философию не платите за то, что вам не нужно».

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

person supercat    schedule 25.02.2015