Вопрос-ответ

What is a StackOverflowError?

Что такое StackOverflowError?

Что такое StackOverflowError, что вызывает это и как я должен с ними бороться?

Переведено автоматически
Ответ 1

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

У вашего процесса также есть куча, которая находится в нижнем конце вашего процесса. По мере выделения памяти эта куча может расти к верхнему краю вашего адресного пространства. Как вы можете видеть, существует вероятность того, что куча "столкнется" со стеком (немного похоже на тектонические плиты !!!).

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

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

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

Если у вас нет очевидных рекурсивных функций, проверьте, вызываете ли вы какие-либо библиотечные функции, которые косвенно вызовут вашу функцию (как в неявном примере выше).

Ответ 2

Если у вас есть функция, подобная:

int foo()
{
// more stuff
foo();
}

Тогда foo() будет продолжать вызывать себя, становясь все глубже и глубже, и когда пространство, используемое для отслеживания того, в каких функциях вы задействованы, заполняется, вы получаете ошибку stack overflow.

Ответ 3

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

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

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

Итак, переполнение стека появляется там, где вы выделяете слишком много в стек. Например, в упомянутой рекурсии.

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

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

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

Ответ 4

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

2024-02-29 14:50 java exception