I'm a complete beginner writing Breakout (the game) in Java. All was going well until I started to get a stack overflow error in the late game. Unfortunately I know that without actually putting the code up online I won't really be able to get help with this. So instead I thought I would make this my first Stackoverflow.com question!

What is a "stack overflow" error, what causes it and how do real programmers deal with them?

10 Answers
10

Parameters and local variables are allocated on the stack (with reference types the object lives on the heap and a variable references that object). 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 the 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. 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 than 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.

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).

Original poster: hey this is great. So recursion is always responsible for stack overflows? Or can other things be responsible for them as well? Unfortunately I am using a library... but not one that I understand.
–
ZiggyOct 18 '08 at 9:04

2

Ha ha ha, so here it is: while (points < 100) {addMouseListeners(); moveball(); checkforcollision(); pause(speed);} Wow do I feel lame for not realizing that I would end up with a stackfull of mouse listeners... Thanks guys!
–
ZiggyOct 18 '08 at 11:26

It should be pointed out that it's almost impossible to "handle" a stack overflow error. In most environments, to handle the error one needs to run code on the stack, which is difficult if there is no more stack space.
–
Hot LicksJan 25 '14 at 14:09

1

@JB King: Doesn't really apply to Java, where only primitive types and references are kept on the stack. All the big stuff (arrays and objects) is on the heap.
–
Jona Christopher SahnwaldtJan 23 at 2:25

Wrong. Your function is tail-recursive. Most compiled languages have tail-recursion optimizations. This means the recursion reduces into a simple loop and you will never hit stack overflow with this piece of code on some systems.
–
CheeryOct 18 '08 at 9:29

Stack overflow means exactly that: a stack overflows. Usually there's a one stack in the program that contains local-scope variables and addresses where to return when execution of a routine ends. That stack tends to be a fixed memory range somewhere in the memory, therefore it's limited how much it can contain values.

If the stack is empty you can't pop, if you do you'll get stack underflow error.

If the stack is full you can't push, if you do you'll get stack overflow error.

So stack overflow appears where you allocate too much into the stack. For instance, in the mentioned recursion.

Some implementations optimize out some forms of recursions. Tail recursion in particular. Tail recursive routines are form of routines where the recursive call appears as a final thing what the routine does. Such routine call gets simply reduced into a jump.

Some implementations go so far as implement their own stacks for recursion, therefore they allow the recursion to continue until the system runs out of memory.

Easiest thing you could try would be to increase your stack size if you can. If you can't do that though, the second best thing would be to look whether there's something that clearly causes the stack overflow. Try it by printing something before and after the call into routine. This helps you to find out the failing routine.

Is there such a thing as a stack underflow ?
–
PacerierJan 29 '12 at 14:09

3

A stack underflow is possible in assembly (popping more than you pushed), though in compiled languages it'd be near impossible. I'm not sure, you might be able to find an implementation of C's alloca() which "supports" negative sizes.
–
Score_UnderFeb 9 '13 at 0:14

A stack overflow is usually called by nesting function calls too deeply (especially easy when using recursion, i.e. a function that calls itself) or allocating a large amount of memory on the stack where using the heap would be more appropriate.

Also, from the original poster here: nesting functions too deeply in what? Other functions? And: how does one allocate memory to the stack or heap (since, you know, I've clearly done one of these things without knowing).
–
ZiggyOct 18 '08 at 8:26

@Ziggy: Yes, if one function calls another function, which calls yet another function, and so on, after many levels, your program will have a stack overflow. [continues]
–
Chris Jester-Young♦Oct 18 '08 at 9:25

[...continued] In Java, you can't directly allocate memory from the stack (whereas in C, you can, and this would then be something to watch for), so that's unlikely to be the cause. In Java, all direct allocations come from the heap, by using "new".
–
Chris Jester-Young♦Oct 18 '08 at 9:26

@ChrisJester-Young Isn't it true that if I have 100 local variables in a method, all of it goes on the stack without exceptions?
–
PacerierJan 29 '12 at 14:08

A stack overflow error usually happens when your function calls nest too deeply. See the Stack Overflow Code Golf thread for some examples of how this happens (though in the case of that question, the answers intentionally cause stack overflow).

I would totally like to add code, but as I don't know what causes stack overflows I am not sure what code to add. adding all the code would be lame, no?
–
ZiggyOct 18 '08 at 8:27

Is your project open-source? If so, just make a Sourceforge or github account, and upload all your code there. :-)
–
Chris Jester-Young♦Oct 18 '08 at 9:37

this sounds like a great idea, but I am such a noob that I don't even know what I would have to upload. Like, the library that I am importing classes that I am extending etc... are all unknowns to me. Oh man: bad times.
–
ZiggyOct 18 '08 at 9:49

Here is an example of a recursive algorithm for reversing a singly linked list. On a laptop with the following spec (4G memory, Intel Core i5 2.3GHz CPU, 64 bit Windows 7), this function will run into StackOverflow error for a linked list of size close to 10,000.

My point is that we should use recursion judiciously, always taking into account of the scale of the system.
Often recursion can be converted to iterative program, which scales better. (One iterative version of the same algorithm is given at the bottom of the page, it reverses a singly linked list of size 1 million in 9 milliseconds.)

To describe the i would like to tell you that the local variable are stored in stack
if you see in the image you will 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 must be used with caution, in order for the StackOverflowError to be avoided.
An example that throws a StackOverflowError is shown below:

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 once we invoke the method, passing 0 as a parameter. However, in our example, we start printing numbers from 1 and thus, the recursion will never terminate.
A sample execution, using the -Xss1M flag that specifies the size of the thread stack to equal to 1MB, 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 512KB, or 1MB. 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[g|G|m|M|k|K]