Does the exception "Stack Overflow" is only linked to the use of recursion? In what other context we can give开发者_运维百科 this exception?
- allocating local variables that are too large to fit on the stack, for example an array with a million elements on a 64K stack.
- too deep a call stack, even without recursion, if each routine has many local variables. example: a() calls b() calls c()...calls z() calls a1()... calls z99(). Each routines local variable as well as a return address for each function (and maybe a stack smashing protector) stays on the stack, until the stack unwinds as each function exits.
If you allocate huge buffers on the stack using C99's dynamic arrays. i.e.
void stackkiller(int size) {
char toohuge[size];
printf("Don't call this with too big an argument!\n");
}
Since any recursive algorithm can be turned into an iterative one and vice versa, here's the algorithm for a stack overflow in C99:
void stackoverflow()
{
for (size_t n = 0; ; n *= 2)
char a[n];
}
(Turn compiler optimization off.)
If you have too much memory allocated on the stack (for example, see in VS compiler).
One important thing to note, is that both deep recursion and deep call chains do not fundamentally cause the stack to overflow. What cause the overflow is that every call allocates a new stack frame, thus adding to the stack space usage.
Many languages allow arbitrarily deep recursion/calls by using tail call optimization. Some languages such as ML and Haskell will internally convert some (when the call is at the end of the calling function) function/recursive calls to avoid using additional stack space, thus allowing effectively infinite recursion. The idea here is that if the call is at the very end of the calling function, the calling functions stack space is no longer needed and can be reclaimed for use by the called function.
精彩评论