2009-03-15 2 views
4

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

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

ответ

14

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

1

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

1

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

4

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

2

Согласно некоторым ответам на this question, стандарты C даже не имеют ничего сказать о существовании стека, не говоря уже о переполнении стека.

8

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

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

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

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

1

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

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

:: Rimshot ::

4

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

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

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

0

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

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

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

0

В этом отношении стандарт 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 (на каждом уровне вызова), чьи сроки жизни все перекрываются, каждый с разными адресами. Это невозможно по простому аргументу подсчета.

Смежные вопросы