2011-02-07 2 views
3

Во многих операционных системах стек и куча начинаются с противоположных сторон виртуального адресного пространства процесса и растут друг к другу. Это позволяет стеку расширяться как можно больше, не ударяя кучу.Как операционная система обнаруживает переполнение стека?

Предположим, что у меня есть программа, которая вызывает переполнение стека. Мое настоящее понимание заключается в том, что это приведет к тому, что стек будет неудержимо расти к куче и, в конечном счете, ударит его. Это верно? Если да, то как операционная система обнаруживает, что происходит переполнение стека? Похоже, что ОС не сможет обнаружить, что программа пытается использовать виртуальную память, выделенную для кучи, как часть стека, поскольку они будут находиться в смежных областях памяти.

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

ответ

3

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

+0

@ CAFxX- Это кажется разумным, но в качестве продолжения предположим, что у меня есть программа с фреймом стека, которая действительно огромна (скажем, больше, чем страница виртуальной памяти). Не было ли тогда, когда моя программа могла бы выделить большое количество страниц для своего стека, а затем «перепрыгнуть» через память после стека и в память для кучи? – templatetypedef

+0

У ОС есть чеки для этого. Когда я сказал, что если это не разумно, это приведет к переполнению стека, я имел в виду, что если стек слишком сильно растет (скажем, например, так много, что вы на самом деле достигаете кучи), даже если в целом предел намного более строгий, зависимая) ОС остановит вас от этого, увеличив переполнение стека - и это, как правило, завершает процесс, так что Bad Things (TM) не происходит. – CAFxX

+1

Я просто подумал, что, возможно, вы спрашиваете о переполнении стека другого типа, т. Е. О том, что приводит к повреждению стека. Это отличается, и обычно проверяется временем выполнения процесса, помещая «часовые» в стек. Если контролер получает перезапись, это означает, что стек был поврежден, а исключение переполнения/коррупции стека было поднято (но, опять же, как правило, время выполнения процесса, а не ОС). – CAFxX

1

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

+0

@ WuHoUnited- В случае с JVM это правда, но JVM - это часть программного обеспечения, которое имитирует стек и кучу и, следовательно, имеет гораздо более активный контроль в управлении им. В частности, он может установить ограничение глубины стека.Мне больше любопытно, что происходит с собственным кодом на языке C или C++, где ОС не отвечает за настройку каждого кадра стека. – templatetypedef

+0

Извините, я читал здесь слишком много java-вопросов. – WuHoUnited

1

Переполнение стека идет назад в стеке - они работают путем перезаписи данных в уже инициализированных частях стека, что возможно, потому что стеки растут вниз.

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

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

1

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

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

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

Я также видел другой подход, используя слова охраны. Стек для каждого процесса распределялся на куче и заполнялся защитными щитами (что-то вроде 0xc0cac01a). Таким образом, было легко получить размер стека для каждого процесса, просто подсчитав защитные слова. Операционная система вызвала панику, если не было ни одного защитного слова.

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