Что такое переполнение стека? - PullRequest
35 голосов
/ 10 июля 2009

Что такое ошибка переполнения стека? В каких программах / языках программирования это может происходить? Это вряд ли произойдет в коде веб-приложения?

Ответы [ 5 ]

26 голосов
/ 10 июля 2009

Из Википедия :

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

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

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

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

stack diagram

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

Гуффа Вклад: Стек не имеет ничего общего со сборкой мусора. Современные приложения имеют больший стек, что делает его немного менее вероятным переполнение стека, но кроме этого нет никакой разницы.

18 голосов
/ 10 июля 2009

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

В этом примере функция Main с именем WriteCustomerDetails и функцией PrintToConsole записывают отдельные биты данных, которые искала функция WriteCustomerDetails:

'======= вершина стека ====================='
Функция: PrintToConsole
Арг: Джон Смит, 34 Акация Авеню, возраст 23
«------------------------------------------------- ---------- '
Функция: WriteCustomerDetails
Арг: Джон Смит
«------------------------------------------------- ---------- '
Функция: Главная
'====== Нижняя часть стека ==================='

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

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

Это может произойти в любой программе, они не обязательно должны быть сложными, и это может происходить в коде, выполняющем веб-сайт. И это может происходить и в скриптовых языках.

7 голосов
/ 10 июля 2009

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

Первое, когда у вас есть ошибка в коде, вызывающая рекурсивный цикл без выхода. Например свойство, читающее из себя:

public int Length {
   get {
      return Length;
   }
}

Второй - когда у вас слишком глубокий рекурсивный цикл. Поскольку пространство стека ограничено, вы можете вкладывать алгоритм только определенное количество раз. Если ваш алгоритм вложен слишком глубоко, так что ему не хватает места в стеке до его существования, вы получаете переполнение стека. Пример:

public bool Odd(int value) {
   if (value == 0) {
      return false;
   } else {
      return !Odd(value - 1);
   }
}

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

6 голосов
/ 10 июля 2009

От Википедия , от couse:

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

1 голос
/ 10 июля 2009

Переполнение стека происходит, когда вы используете стек (duh ...) и возникает проблема выделения / чтения памяти. в «веб-программах», как вы выразились (я полагаю, вы говорите о HTML, PHP, JS), либо вы не используете стеки, либо используемый язык не допускает низкоуровневое управление памятью, которое предотвращает эти проблемы.

...