Переповнення стека

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

В програмному забезпеченні, переповнення стека (англ. stack overflow) відбувається у випадку коли забагато пам'яті використовується для стека викликів. Стек викликів містить обмежену кількість пам'яті, часто визначену при старті програми. Розмір стека викликів залежить від багатьох факторів, включно з мовою програмування, машинною архітектурою, багатозадачністю і загальним обсягом доступної пам'яті. Коли використовується забагато пам'яті для стека викликів, тоді кажуть, що стек переповнився, зазвичай це виливається в крах програми. [1] Цей тип помилок зазвичай трапляється в результаті двох помилок програмування.[2]

Нескінченна рекурсія[ред. | ред. код]

Найзвичайніша причина помилки переповнення стека це надзвичайно глибока або нескінченна рекурсія. Деякі мови програмування дозволяють нескінченну рекурсію, наприклад, Scheme, яка дозволяє специфічний тип рекурсії — хвостову рекурсію. Це можливо через непотрібність заштовхування адреси повернення в стек.[3]

Приклад нескінченної рекурсії на C.

main() {
     main();
}

Функція main, яка завжди виконується першою, викликає сама себе до моменту переповнення стека.

Занадто великі стекові змінні[ред. | ред. код]

Інша важлива причина переповнення стека це спроба виділити у стеку більше пам'яті ніж він може виділити. Зазвичай це відбувається при створені занадто великих локальних змінних. З цієї причини змінні великого розміру бажано розміщати динамічно.[4]

Приклад дуже великої стекової змінної на C.

main() {
     double x[1000000];
}

Цей масив вимагає майже 8 мегабайт пам'яті (припускаємо, що розмір double становить 8), це більше, ніж виділено на стек.

Можливість виникнення цієї помилки збільшується при деяких обставинах. Наприклад, одна й та сама програма при виконанні в одному потоці може працювати добре, а при переході до багатопотоковості програма може зазнавати краху. Це відбувається через те, що кожне завдання буде мати менший розмір стека, ніж один загальний поток в однопотоковому варіанті.

Дивись також[ред. | ред. код]

Зноски[ред. | ред. код]

  1. Burley, James Craig (1 червня 1991). Using and Porting GNU Fortran. Архів оригіналу за 5 жовтня 2012. Процитовано 5 вересня 2010.
  2. Danny, Kalev (5 вересня 2000). Understanding Stack Overflow. Архів оригіналу за 5 жовтня 2012. Процитовано 5 вересня 2010.
  3. An Introduction to Scheme and its Implementation. 19 лютого 1997. Архів оригіналу за 10 серпня 2007. Процитовано 5 вересня 2010.
  4. Feldman, Howard (23 листопада 2005). Modern Memory Management, Part 2. Архів оригіналу за 5 жовтня 2012. Процитовано 5 вересня 2010.