Stackoverflow что это за ошибка
Перейти к содержимому

Stackoverflow что это за ошибка

  • автор:

Ошибка "Stack overflow" — что это и как ее избежать?

Можете объяснить, когда возникает эта ошибка и как от нее избавиться?

Harry's user avatar

Это означает, что в стеке недостаточно места.

Причины — например, слишком глубокая рекурсия (редко), или слишком большие локальные переменные (куда чаще), или и то и другое сразу 🙂

Как избавиться? Опять же, можно просто в настройках компилятора поднять размер стека.

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

практически гарантированно даст переполнение стека. В отличие от

Словом, смотрите, кто съедает много стековой памяти, и избавляйтесь от него.

Harry's user avatar

Про стек и другие типы данных:

  • Стековые данные. На них память выделяется при заходе в процедуру и освобождается при её завершении. Максимальный размер стека программы составляет 1 GB и для 32-битных, и для 64-битных приложений. (Размерстека задаётся линковщиком и по умолчанию составляет 1 MB)
  • Статические данные. Ограничение накладывается на размер самого исходного кода программы и размер статически выделяемой памяти. В языке C++ такие данные обычно представлены переменными, объявленными на глобальном уровне вне процедур. Как для 32-битных, так и для 64-битных программ, ограничение на размер статически выделяемой памяти равно 2 GB.
  • Динамические данные. Это данные, память на которые динамически выделяется во время исполнения программы. В C++ такое выделение обычно осуществляется функцией malloc или оператором new. В 32-битных программах размер динамически выделяемой памяти ограничен 2 GB, в 64-битных — 8 TB.

У 32-битного приложения запущенного в 32-битной Windows суммарный размер всех перечисленных типов данных не должен превышать 2 GB. (Практически ограничение равно 1.75GB из-за требований к памяти самой операционной системы) 32-битная программа, собранная с ключом /LARGEADDRESSAWARE:YES может выделять до 3-х гигабайт памяти, если 32-битная операционная система Windows запущена с ключом /3gb. Эта же 32-битная программа, запущенная на 64-битной системе, может выделить почти 4 GB памяти (на практике около 3.5 GB).

Ограничения на максимальный размер статически-выделяемой и стековой памяти одинаковы для 32-х и 64-х битных Windows приложений. Это связано с форматом типа файлов Portable Executable (PE), который используется в Windows для описания exe и dll файлов. Статические и стековые данные располагаются в первых 2-х GB адресного пространства приложения. Стоит помнить, что данные ограничения накладываются самой операционной системой и не зависят от используемого компилятора.

Want to learn more about the potential causes and solutions to the StackOverFlowError in your JVM project? Check out this post to learn more.

Abdisalam Mohamed

StackOverFlowError is one of the common confronted JVM errors. In this blog post, we will look at the inner mechanics of thread stacks, reasons that can trigger StackOverFlowError, and potential solutions to address this error.

To gain deeper understanding into StackOverFlowError, let’s review this simple program:

This program is very simple with the following execution code:

  1. main() method is invoked first
  2. main() method invokes a() method. Inside a() method, the integer variable ‘x’ is initialized to value 0.
  3. a() method in turn invokes b() method. Inside b() method, the Car object is constructed and assigned to variable ‘y.'
  4. b() method in turn invokes the c() method. Inside the c() method, the float variable ‘z’ is initialized to value 0.

Now, let’s review what happens behind the scenes when above simple program is executed. Each thread in the application has its own stack. Each stack has multiple stack frames. The thread adds the methods it’s executing, primitive data types, object pointers, and return values to its stack frame in the sequence order in which they are executed.

Fig 1: Thread’s Stack frame

Step #1: main() method is pushed into the application thread’s stack.

Step #2: a() method is pushed into application thread’s stack. In a() method, primitive data type ‘int’ is defined with value 0 and assigned to variable x. This information is also pushed into the same stack frame. Note that both data, i.e. ‘0’ and variable ‘x,' is pushed into thread’s stack frame.

Step #3: b() method is pushed into thread’s stack. In the b() method, the Car object is created and assigned to variable ‘y.' A crucial point to note here is that the ‘Car’ object is created in the heap and not in the thread’s stack. Only the Car object’s reference, i.e. y, is stored in the thread’s stack frame.

Step #4: c() method is pushed into thread’s stack. In c() method, primitive data type ‘float’ is defined with value 0f and assigned to variable z. This information is also pushed into same stack frame. Note both data, i.e. ‘0f’ and variable ‘z,’ is pushed into thread’s stack frame.

Once each method’s execution is completed, then the method and the variables/object pointers are stored in the stack frame are removed, as shown in Fig 2.

Fig 2: Thread’s stack frame after executing methods

What Causes StackOverflowError?

As you can see, thread’s stack is storing methods it’s executing, primitive datatypes, variables, object pointers, and return values. All of these consume memory. If thread’s stack sizes grow beyond the allocated memory limit, then StackOverflowError is thrown. Let’s look at the below buggy program, which will result in a StackOverflowError :

In this program, the main() method invokes a() method. a() method recursively calls itself. This implementation will cause a() method to be invoked infinite number of times. In this circumstance, a() method will be added to thread’s stack frame infinite number of times. Thus, after a few thousand iterations, thread’s stack size limit would be exceeded. Once stack size limit is exceeded, it will result in StackOverflowError :

Fig 3: StackOverflowError progression

What Are the Solutions to StackOverflowError?

There are couple of strategies to address StackOverflowError .

1. Fix the Code

Because of a non-terminating recursive call (as shown in the above example), threads stack size can grow to a large size. In those circumstances, you must fix the source code that is causing recursive looping. When ‘StackOverflowError’ is thrown, it will print the stacktrace of the code that it was recursively executing. This code is a good pointer to start debugging and fixing the issue. In the above example, it’s the a() method.

2. Increase Thread Stack Size (-Xss)

There might be legitimate reason where a threads stack size needs to be increased. Maybe thread has to execute large number of methods or lot of local variables/created in the methods thread has been executing? In such circumstances, you can increase the thread’s stack size using the JVM argument: ‘-Xss.” This argument needs to be passed when you start the application. Example:

This will set the thread’s stack size to 2 mb.

It might bring a question: what is the default thread’s stack size? Default thread stack size varies based on your operating system, Java version, and vendor.

Что такое ошибка stackoverflow

To describe this, first let us understand how local variables and objects are stored.

Local variable are stored on the stack:

Enter image description here

If you looked at the image you should be able to understand how things are working.

When a function call is invoked by a Java application, a stack frame is allocated on the call stack. The stack frame contains the parameters of the invoked method, its local parameters, and the return address of the method. The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the StackOverflowError is thrown by the Java Virtual Machine (JVM).

The most common case that can possibly exhaust a Java application’s stack is recursion. In recursion, a method invokes itself during its execution. Recursion is considered as a powerful general-purpose programming technique, but it must be used with caution, to avoid StackOverflowError .

An example of throwing a StackOverflowError is shown below:

StackOverflowErrorExample.java:

In this example, we define a recursive method, called recursivePrint that prints an integer and then, calls itself, with the next successive integer as an argument. The recursion ends until we pass in 0 as a parameter. However, in our example, we passed in the parameter from 1 and its increasing followers, consequently, the recursion will never terminate.

A sample execution, using the -Xss1M flag that specifies the size of the thread stack to equal to 1 MB, is shown below:

Depending on the JVM’s initial configuration, the results may differ, but eventually the StackOverflowError shall be thrown. This example is a very good example of how recursion can cause problems, if not implemented with caution.

How to deal with the StackOverflowError

The simplest solution is to carefully inspect the stack trace and
detect the repeating pattern of line numbers. These line numbers
indicate the code being recursively called. Once you detect these
lines, you must carefully inspect your code and understand why the
recursion never terminates.

If you have verified that the recursion
is implemented correctly, you can increase the stack’s size, in
order to allow a larger number of invocations. Depending on the Java
Virtual Machine (JVM) installed, the default thread stack size may
equal to either 512 KB, or 1 MB. You can increase the thread stack
size using the -Xss flag. This flag can be specified either via the
project’s configuration, or via the command line. The format of the
-Xss argument is:
-Xss<size>[g|G|m|M|k|K]

В мире программистов ошибка «stack overflow» очень известн а б лагодаря тому, что этот вид ошибки довольно распространен. А сам термин «stack overflow» известен еще больше , чем ошибка, благодаря одноименному англоязычному ресурсу «StackOverflow». Это сообщество программистов международного масштаба , и еще куча всего интересного. Поэтому не нужно путать ошибку « stack overflow » и веб-ресурс с таким же названием. В нашей статье речь пойдет об ошибке.

Ошибка «stack overflow» связана с переполнением стека. Она появляется в том случае, когда в стеке должно сохранит ь ся больше информации, чем он может уместить. Объем памяти стека задает программист при запуске программы. Если в процессе выполнения программы стек переполняется, тогда возникает ошибка « stack overflow » и программа аварийно завершает работу. Причин возникновения подобной ошибки может быть несколько.

Ошибка « stack overflow »

  • бесконечная рекурсия;

  • глубокая рекурсия;

  • проблемы с переменными в стеке.

Бесконечная рекурсия и ошибка «stack overflow»

  • забывает прописывать условие для выхода из рекурсии;

  • пишет неосознанную косвенную рекурсию.

if (number == 0)

return 1;

return number * factorial(number — 1);

>

В описанном примере прописаны условия выхода из рекурсии, однако они никогда не сработают, если «number» будет отрицательным. Поэтому через несколько миллионов вызовов стек будет переполнен и возникнет ошибка «stack overflow». В некоторых языках программирования предусмотрена «защита» от таких рекурсий. В ни х р екурсия из конца функции конвертируется в цикл, что не будет расходовать стековую память. Н о п одобная «оптимизация» вызовет другую , менее опасную проблему — «зацикливание».

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

В коде это выглядит так:

int Object::getNumber(int index, bool& isChangeable)

<

isChangeable = true;

return getNumber(index);

>

int Object::getNumber(int index)

<

bool noValue;

return getNumber(index, noValue);

>

Глубокая рекурсия и ошибка «stack overflow»

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

  • «вынести» рекурсию за пределы аппаратного стека в динамический;

  • и другое.

Проблемы с переменными в стеке и ошибка «stack overflow»

Если взглянуть на популярность возникновения «stack overflow error», то причина с проблемными переменными в стеке стоит на первом месте. Кроется она в том, что программист изначально выделяет слишком много памяти локальной переменной.

Например:

int function() <

double b[1000000]

>

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

Заключение

Ошибка « stack overflow » возникает довольно часто. Каждый конкретный случай ее возникновения требует собственного решения. Одна причина объединяет возникновение такой ошибки — невнимательность программиста. Если « stack overflow error » возникла, значит , программист где-то что-то упустил или не доглядел.

To describe this, first let us understand how local variables and objects are stored.

Local variable are stored on the stack:

Enter image description here

If you looked at the image you should be able to understand how things are working.

When a function call is invoked by a Java application, a stack frame is allocated on the call stack. The stack frame contains the parameters of the invoked method, its local parameters, and the return address of the method. The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the StackOverflowError is thrown by the Java Virtual Machine (JVM).

The most common case that can possibly exhaust a Java application’s stack is recursion. In recursion, a method invokes itself during its execution. Recursion is considered as a powerful general-purpose programming technique, but it must be used with caution, to avoid StackOverflowError .

An example of throwing a StackOverflowError is shown below:

StackOverflowErrorExample.java:

In this example, we define a recursive method, called recursivePrint that prints an integer and then, calls itself, with the next successive integer as an argument. The recursion ends until we pass in 0 as a parameter. However, in our example, we passed in the parameter from 1 and its increasing followers, consequently, the recursion will never terminate.

A sample execution, using the -Xss1M flag that specifies the size of the thread stack to equal to 1 MB, is shown below:

Depending on the JVM’s initial configuration, the results may differ, but eventually the StackOverflowError shall be thrown. This example is a very good example of how recursion can cause problems, if not implemented with caution.

How to deal with the StackOverflowError

The simplest solution is to carefully inspect the stack trace and
detect the repeating pattern of line numbers. These line numbers
indicate the code being recursively called. Once you detect these
lines, you must carefully inspect your code and understand why the
recursion never terminates.

If you have verified that the recursion
is implemented correctly, you can increase the stack’s size, in
order to allow a larger number of invocations. Depending on the Java
Virtual Machine (JVM) installed, the default thread stack size may
equal to either 512 KB, or 1 MB. You can increase the thread stack
size using the -Xss flag. This flag can be specified either via the
project’s configuration, or via the command line. The format of the
-Xss argument is:
-Xss<size>[g|G|m|M|k|K]

To describe this, first let us understand how local variables and objects are stored.

Local variable are stored on the stack:

Enter image description here

If you looked at the image you should be able to understand how things are working.

When a function call is invoked by a Java application, a stack frame is allocated on the call stack. The stack frame contains the parameters of the invoked method, its local parameters, and the return address of the method. The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the StackOverflowError is thrown by the Java Virtual Machine (JVM).

The most common case that can possibly exhaust a Java application’s stack is recursion. In recursion, a method invokes itself during its execution. Recursion is considered as a powerful general-purpose programming technique, but it must be used with caution, to avoid StackOverflowError .

An example of throwing a StackOverflowError is shown below:

StackOverflowErrorExample.java:

In this example, we define a recursive method, called recursivePrint that prints an integer and then, calls itself, with the next successive integer as an argument. The recursion ends until we pass in 0 as a parameter. However, in our example, we passed in the parameter from 1 and its increasing followers, consequently, the recursion will never terminate.

A sample execution, using the -Xss1M flag that specifies the size of the thread stack to equal to 1 MB, is shown below:

Depending on the JVM’s initial configuration, the results may differ, but eventually the StackOverflowError shall be thrown. This example is a very good example of how recursion can cause problems, if not implemented with caution.

How to deal with the StackOverflowError

The simplest solution is to carefully inspect the stack trace and
detect the repeating pattern of line numbers. These line numbers
indicate the code being recursively called. Once you detect these
lines, you must carefully inspect your code and understand why the
recursion never terminates.

If you have verified that the recursion
is implemented correctly, you can increase the stack’s size, in
order to allow a larger number of invocations. Depending on the Java
Virtual Machine (JVM) installed, the default thread stack size may
equal to either 512 KB, or 1 MB. You can increase the thread stack
size using the -Xss flag. This flag can be specified either via the
project’s configuration, or via the command line. The format of the
-Xss argument is:
-Xss<size>[g|G|m|M|k|K]

StackOverFlowError is one of the common confronted JVM errors. In this blog post, we will look at the inner mechanics of thread stacks, reasons that can trigger StackOverFlowError, and potential solutions to address this error.

To gain deeper understanding into StackOverFlowError, let’s review this simple program:

This program is very simple with the following execution code:

  1. main() method is invoked first
  2. main() method invokes a() method. Inside a() method, the integer variable ‘x’ is initialized to value 0.
  3. a() method in turn invokes b() method. Inside b() method, the Car object is constructed and assigned to variable ‘y.’
  4. b() method in turn invokes the c() method. Inside the c() method, the float variable ‘z’ is initialized to value 0.

Now, let’s review what happens behind the scenes when above simple program is executed. Each thread in the application has its own stack. Each stack has multiple stack frames. The thread adds the methods it’s executing, primitive data types, object pointers, and return values to its stack frame in the sequence order in which they are executed.

thread-stack-frame-1

Fig 1: Thread’s Stack frame

Step #1: main() method is pushed into the application thread’s stack.

Step #2: a() method is pushed into application thread’s stack. In a() method, primitive data type ‘int’ is defined with value 0 and assigned to variable x. This information is also pushed into the same stack frame. Note that both data, i.e. ‘0’ and variable ‘x,’ is pushed into thread’s stack frame.

Step #3: b() method is pushed into thread’s stack. In the b() method, the Car object is created and assigned to variable ‘y.’ A crucial point to note here is that the ‘Car’ object is created in the heap and not in the thread’s stack. Only the Car object’s reference, i.e. y, is stored in the thread’s stack frame.

Step #4: c() method is pushed into thread’s stack. In c() method, primitive data type ‘float’ is defined with value 0f and assigned to variable z. This information is also pushed into same stack frame. Note both data, i.e. ‘0f’ and variable ‘z,’ is pushed into thread’s stack frame.

Once each method’s execution is completed, then the method and the variables/object pointers are stored in the stack frame are removed, as shown in Fig 2.

thread-stack-frame-2

https://amdy.su/wp-admin/options-general.php?page=ad-inserter.php#tab-8

Fig 2: Thread’s stack frame after executing methods

What Causes StackOverflowError?

As you can see, thread’s stack is storing methods it’s executing, primitive datatypes, variables, object pointers, and return values. All of these consume memory. If thread’s stack sizes grow beyond the allocated memory limit, then StackOverflowError is thrown. Let’s look at the below buggy program, which will result in a StackOverflowError :

In this program, the main() method invokes a() method. a() method recursively calls itself. This implementation will cause a() method to be invoked infinite number of times. In this circumstance, a() method will be added to thread’s stack frame infinite number of times. Thus, after a few thousand iterations, thread’s stack size limit would be exceeded. Once stack size limit is exceeded, it will result in StackOverflowError :

stackOverflowError

Fig 3: StackOverflowError progression

What Are the Solutions to StackOverflowError?

There are couple of strategies to address StackOverflowError .

1. Fix the Code

Because of a non-terminating recursive call (as shown in the above example), threads stack size can grow to a large size. In those circumstances, you must fix the source code that is causing recursive looping. When ‘StackOverflowError’ is thrown, it will print the stacktrace of the code that it was recursively executing. This code is a good pointer to start debugging and fixing the issue. In the above example, it’s the a() method.

2. Increase Thread Stack Size (-Xss)

There might be legitimate reason where a threads stack size needs to be increased. Maybe thread has to execute large number of methods or lot of local variables/created in the methods thread has been executing? In such circumstances, you can increase the thread’s stack size using the JVM argument: ‘-Xss.» This argument needs to be passed when you start the application. Example:

This will set the thread’s stack size to 2 mb.

It might bring a question: what is the default thread’s stack size? Default thread stack size varies based on your operating system, Java version, and vendor.

JVM version

Thread stack size

Sparc 32-bit JVM

Sparc 64-bit JVM

x86 Solaris/Linux 32-bit JVM

x86 Solaris/Linux 64-bit JVM

Windows 32-bit JVM

Windows 64-bit JVM

Data Types
Frame (networking)
Java (programming language)
Java virtual machine
32-bit
64-bit
Primitive data type

Opinions expressed by DZone contributors are their own.

StackOverflowError в Java

1. обзор

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

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

2. Фреймы стека и как происходитStackOverflowError

Давайте начнем с основ. When a method is called, a new stack frame gets created on the call stack. Этот кадр стека содержит параметры вызванного метода, его локальные переменные и адрес возврата метода, т.е. точка, с которой выполнение метода должно продолжаться после возврата вызванного метода.

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

Во время этого процесса, если JVM обнаруживает ситуацию, когда нет места для создания нового кадра стека, она выдастStackOverflowError.

Наиболее частая причина, по которой JVM может столкнуться с этой ситуацией, —unterminated/infinite recursion — в описании Javadoc дляStackOverflowError упоминается, что ошибка возникает в результате слишком глубокой рекурсии в конкретном фрагменте кода.

Однако рекурсия не является единственной причиной этой ошибки. Это также может произойти в ситуации, когда приложение хранитcalling methods from within methods until the stack is exhausted. Это редкий случай, так как ни один разработчик не будет намеренно следовать плохой практике кодирования Другая редкая причина —having a vast number of local variables inside a method.

StackOverflowError также может быть выброшено, если приложение разработано для использованияcyclic relationships between classes. В этой ситуации конструкторы друг друга вызывают неоднократно, что приводит к возникновению этой ошибки. Это также можно рассматривать как форму рекурсии.

Другой интересный сценарий, который вызывает эту ошибку, — этоclass is being instantiated within the same class as an instance variable of that class. Это приведет к тому, что конструктор одного и того же класса будет вызываться снова и снова (рекурсивно), что в конечном итоге приведет кStackOverflowError.

В следующем разделе мы рассмотрим несколько примеров кода, демонстрирующих эти сценарии.

3. StackOverflowError в действии

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

Здесь ошибка выдается во всех случаях для любого значения, переданного в метод:

Однако в следующем примере указано условие завершения, но оно никогда не выполняется, если значение-1 передается методуcalculateFactorial(), что вызывает незавершенную / бесконечную рекурсию:

Этот набор тестов демонстрирует этот сценарий:

В этом конкретном случае ошибки можно было бы полностью избежать, если бы условие завершения было просто сформулировано как:

Вот тест, который демонстрирует этот сценарий на практике:

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

Теперь предположим, что мы пытаемся создать экземплярClassOne, как показано в этом тесте:

В итоге получаетсяStackOverflowError, поскольку конструкторClassOne создает экземплярClassTwo,, а конструкторClassTwo снова создает экземплярClassOne.. И это происходит неоднократно, пока он не переполнится. стек.

Далее мы рассмотрим, что происходит, когда создается экземпляр класса в том же классе, что и переменная экземпляра этого класса.

Как видно в следующем примере,AccountHolder создает экземпляр переменной экземпляраjointAccountHolder:

Когда создается экземпляр классаAccountHolder,, вызываетсяStackOverflowError из-за рекурсивного вызова конструктора, как показано в этом тесте:

4. Работа сStackOverflowError

Лучшее, что можно сделать при обнаруженииStackOverflowError, — это осторожно изучить трассировку стека, чтобы определить повторяющийся шаблон номеров строк. Это позволит нам найти код с проблемной рекурсией.

Давайте рассмотрим несколько трассировок стека, вызванных примерами кода, которые мы видели ранее.

Эта трассировка стека создаетсяInfiniteRecursionWithTerminationConditionManualTest, если мы опускаем объявление исключенияexpected:

Здесь строка № 5 видна повторяющейся. Это где рекурсивный вызов делается. Теперь остается просто изучить код, чтобы убедиться, что рекурсия выполнена правильно.

Вот трассировка стека, которую мы получаем, выполняяCyclicDependancyManualTest (опять же, без исключенияexpected):

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

Как только код тщательно проверен, и если ни одно из следующего (или любая другая логическая ошибка кода) не является причиной ошибки:

Неправильно реализованная рекурсия (т.е. без условия прекращения)

Циклическая зависимость между классами

Создание класса внутри того же класса, что и переменная экземпляра этого класса

Было бы неплохо попробовать увеличить размер стека. В зависимости от установленной JVM размер стека по умолчанию может варьироваться.

Флаг-Xss можно использовать для увеличения размера стека либо из конфигурации проекта, либо из командной строки.

5. Заключение

В этой статье мы более подробно рассмотрелиStackOverflowError, включая то, как код Java может вызывать это, и как мы можем диагностировать и исправить это.

Исходный код, относящийся к этой статье, можно найтиover on GitHub.

StackOverflowError просто сигнализирует о том, что памяти больше нет. Он расширяет класс VirtualMachineError, что указывает на то, что JVM (виртуальная машина Java) повреждена или у нее закончились ресурсы и она не может работать.

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

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

Причина использования StackOverflowError

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

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

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

Что такое stacktrace?

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

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

What is a StackOverflowError?

What is a StackOverflowError , what causes it, and how should I deal with them?

chrylis -cautiouslyoptimistic-'s user avatar

15 Answers 15

Parameters and local variables are allocated on the stack (with reference types, the object lives on the heap and a variable in the stack references that object on the heap). The stack typically lives at the upper end of your address space and as it is used up it heads towards the bottom of the address space (i.e. towards zero).

Your process also has a heap, which lives at the bottom end of your process. As you allocate memory, this heap can grow towards the upper end of your address space. As you can see, there is a potential for the heap to «collide» with the stack (a bit like tectonic plates. ).

The common cause for a stack overflow is a bad recursive call. Typically, this is caused when your recursive functions doesn’t have the correct termination condition, so it ends up calling itself forever. Or when the termination condition is fine, it can be caused by requiring too many recursive calls before fulfilling it.

However, with GUI programming, it’s possible to generate indirect recursion. For example, your app may be handling paint messages, and, whilst processing them, it may call a function that causes the system to send another paint message. Here you’ve not explicitly called yourself, but the OS/VM has done it for you.

To deal with them, you’ll need to examine your code. If you’ve got functions that call themselves then check that you’ve got a terminating condition. If you have, then check that when calling the function you have at least modified one of the arguments, otherwise there’ll be no visible change for the recursively called function and the terminating condition is useless. Also mind that your stack space can run out of memory before reaching a valid terminating condition, thus make sure your method can handle input values requiring more recursive calls.

If you’ve got no obvious recursive functions then check to see if you’re calling any library functions that indirectly will cause your function to be called (like the implicit case above).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *