views:

372

answers:

10

Without using recursion how can a stack overflow exception be thrown?

+9  A: 

Declare an ENORMOUS array as a local variable.

JustJeff
Most compilers will simply not compile this. That's not a stack overflow.
Chris Lutz
@Chris - Won't compile it? I thought that the maximum stack size was set by the linker, and not known to the compiler.
ChrisW
the compiler can't catch it, unless the compiler is capable of analyzing the code for projected run-time stack usage, which could be extremely tricky.
JustJeff
+6  A: 

If you call enough methods, a stack overflow can occur anytime. Although, if you get stack overflow errors without using recursion, you may want to rethink how you're doing things. It's just so easy with recursion because in an infinite loop, you call a ton of methods.

nasufara
+1  A: 

Every method call that has not yet returned consumes some stack space. (Methods with more local variables consume more space.) A very deep call stack can result in stack overflow.

Note that on systems with limited memory (mobile devices and such) you don't have much stack space and will run out sooner.

Artelius
I worked on one console project where our processes had 32K stacks. In one of the routines, there were two 16K arrays. Although the use of the arrays was exclusive and they were not in the same scope, the compiler still allocated 32K of stack space and overflowed our stack (theoretically a smarter compiler would have only reserved 16K). I changed them both to alloc/free to fix the problem.
Adisak
+10  A: 

Since no one else has mentioned it:

throw new System.StackOverflowException();

You might do this when testing or doing fault-injection.

Brian
Great - assuming you're using .NET =)
Erik Forbes
+1  A: 

If you're talking about C++ with a reasonable standard library, I image that this would work:

while (true) {
    alloca(1024 * 1024); // arbitrary - 1M per iteration.
}

Details on alloca.

plinth
Is that a stackoverflow or out of memory exception?
Juliet
@juliet:The alloca() function allocates space in the stack frame of the caller.
pierr
This should not throw an exception if alloca() is properly implemented. The call alloca() is supposed to return NULL if there is not enough stack space rather than throw an exception. What should happen is that after you run out of stack space, your code will be stuck in an infinite loop of alloca() calls returning NULLs.
Adisak
From the link in your answer: RETURN VALUES - The alloca() function returns a null pointer if there is insufficient memory.
Adisak
ah, good point.
plinth
Might want to change the loop to `while(true) { char *c = alloca(1024 * 1024); c[1024 * 1024 - 1] = 0; }` (although that's a segfault, not a stack overflow, but on my system the code `int main(void) { return main(); }` (compiled as C) segfaults).
Chris Lutz
+1  A: 

Short answer: if you have an object which calls an internal object, you increase the stack trace by 1. So, if you have 1000s of objects nested inside one another, each calling its internal object, eventually you'll get a stack overflow.

Here's a demonstration of how to generate primes using nested iterators:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            IEnumerator<int> primes = p.AllPrimes().GetEnumerator();
            int numberOfPrimes = 1000;
            for (int i = 0; i <= numberOfPrimes; i++)
            {
                primes.MoveNext();
                if (i % 1000 == 0)
                {
                    Console.WriteLine(primes.Current);
                }
            }
            Console.ReadKey(true);
        }

        IEnumerable<int> FilterDivisors(IEnumerator<int> seq, int num)
        {
            while (true)
            {
                int current = seq.Current;
                if (current % num != 0)
                {
                    yield return current;
                }
                seq.MoveNext();
            }
        }

        IEnumerable<int> AllIntegers()
        {
            int i = 2;
            while (true)
            {
                yield return i++;
            }
        }

        IEnumerable<int> AllPrimes()
        {
            IEnumerator<int> nums = AllIntegers().GetEnumerator();
            while (true)
            {
                nums.MoveNext();
                int prime = nums.Current;
                yield return prime;

                // nested iterator makes a big boom     
                nums = FilterDivisors(nums, prime).GetEnumerator();
            }
        }
    }
}

There's no recursion, but the program will throw a stack overflow exception after around 150,000 primes.

Juliet
ncie code, reminds me of Evolution of Haskell programmer :)(ton of code against oneliner - programming a factorial)
Juraj Blahunka
+2  A: 

The following applies to Windows, but most OSs implement this in a similar fashion.

The short answer is: if you touch the last guard page, it will throw.

An exception of type EXCEPTION_STACK_OVERFLOW (C00000FD) is raised when your application touches the bottom page of the stack, that is marked a PAGE_GUARD protection flag, and there is no room to grow the stack (commit one more page), see How to trap stack overflow in a Visual C++ application.
The typical case when this happens is when the stack has grown as the result of many function frames on the stack (ie. out of control recursion), as the result of fewer frames but very large frame sizes (functions with a very large local scoped object) or by explicitly allocating from the stack with _alloca.
Another way to cause the exception is to simply intentionally touch the guard page, eg. by dereferencing a pointer that points into that page. This can happen due to a variable initializion bug.

Stack overflows can occur on valid execution paths if the input causes a very deep nesting level. For instance see Stack overflow occurs when you run a query that contains a large number of arguments inside an IN or a NOT IN clause in SQL Server.

Remus Rusanu
A: 

Easiest way to make a StackOverflowException is the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            SomeClass instance = new SomeClass();
            string name = instance.Name;
        }
    }

    public class SomeClass
    {
        public string Name
        {
            get
            {
                return Name;
            }
        }
    }
}
Vladimir Georgiev
Actually this is the 2nd easiest way after just throwing the exception :)
Vladimir Georgiev
The question specifically excluded recursion.
meriton
You are correct, my mistake.
Vladimir Georgiev
A: 

You can run out of stack space without infinite recursion just by having bounded recursion that exceed the stack space (yes it's still recursion).

One example is trying to recursively process a very large binary tree that is pathologically unbalanced (i.e. it looks like a linked list).

Adisak
To quote the question: " **Without using recursion** how can a stack overflow exception be thrown?"
Chris Lutz
That's why I wrote "(yes it's still recursion)" :-)
Adisak
A: 
int main()
{
  //something on the stack
  int foo = 0;
  for (
    //pointer to an address on the stack
    int* p = &foo;
    //forever
    ;
    //ever lower on the stack (assuming that the stack grows downwards)
    --p)
  {
    //write to the stack
    *p = 42;
  }
}
ChrisW