- Переполнение стека
-
В программном обеспечении переполнение стека (англ. stack overflow) возникает, когда в стеке вызовов хранится больше информации, чем он может держать. Обычно ёмкость стека задаётся при старте программы/потока. Когда указатель стека выходит за границы, программа аварийно завершает работу.[1]
Эта ошибка случается по двум причинам.[2]
Содержание
Бесконечная рекурсия
Основная причина переполнения стека — излишне глубокая или бесконечная рекурсия. Простейший пример бесконечной рекурсии на Си:
int foo() { return foo(); }
Функция будет вызывать сама себя, расходуя пространство в стеке, пока стек не переполнится и не случится ошибка сегментации.[3]
Многие языки делают оптимизацию, именуемую «хвостовая рекурсия». Рекурсия, находящаяся в конце функции, превращается в цикл и не расходует стека.[4]
Большие переменные в стеке
Вторая большая причина переполнения стека — одноразовое выделение огромного количества памяти крупными локальными переменными. Многие авторы рекомендуют выделять память, превышающую несколько килобайт, в «куче», а не на стеке.[5]
Пример на Си:
int foo() { double x[1000000]; }
Массив занимает 8 мегабайт памяти; если в стеке нет такого количества памяти, случится переполнение.
Всё, что уменьшает эффективный размер стека, увеличивает риск переполнения. Например, потоки обычно берут стека меньше, чем основная программа — поэтому программа может работать в однопоточном режиме и отказывать в многопоточном. Работающие в режиме ядра подпрограммы часто пользуются чужим стеком, поэтому при программировании в режиме ядра стараются не применять рекурсию и большие локальные переменные.[6][7]
См. также
- Переполнение буфера
- Стек вызовов
- Переполнение памяти
Примечания
- ↑ Burley, James Craig Using and Porting GNU Fortran (1 июня 1991). Архивировано из первоисточника 5 октября 2012.
- ↑ Danny, Kalev Understanding Stack Overflow (5 сентября 2000). Архивировано из первоисточника 5 октября 2012.
- ↑ What is the difference between a segmentation fault and a stack overflow? at StackOverflow
- ↑ An Introduction to Scheme and its Implementation (19 февраля 1997).(недоступная ссылка — история)
- ↑ Feldman, Howard Modern Memory Management, Part 2 (23 ноября 2005). Архивировано из первоисточника 5 октября 2012.
- ↑ Kernel Programming Guide: Performance and Stability Tips. Apple Inc. (7 ноября 2006).(недоступная ссылка — история)
- ↑ Dunlap, Randy Linux Kernel Development: Getting Started (19 мая 2005). Архивировано из первоисточника 5 октября 2012.
На эту статью не ссылаются другие статьи Википедии. Пожалуйста, воспользуйтесь подсказкой и установите ссылки в соответствии с принятыми рекомендациями.Категории:- Ошибки программирования
- Стек
Wikimedia Foundation. 2010.