Sunny Ahuwanya's Blog

Mostly notes on .NET and C#

StackOverflowException and the x64 platform

The StackOverflowException is one of the three deadly exceptions. The other two being the OutOfMemoryException and the ThreadAbortException. These exceptions are deadly because they can theoretically occur anywhere in an application and terminate the process. Also, developers hardly ever prepare for them and are caught unawares when they occur.

Of these three, the StackOverflowException is arguably the deadliest because it cannot be caught when it is thrown by the runtime. 
That's right. When a StackOverflowException is thrown by the runtime (not when it is thrown by the application), try blocks are not processed and the program is promptly terminated. This is the default behavior and cannot be changed unless there is a custom CLR host involved.

This is conventional .NET wisdom that has been time tested and proven, so you can imagine my surprise when a condition that should have caused a StackOverflowException and subsequent process termination, did not.

If you compile following code, target the x86 platform in release mode and run it from your desktop:

class Program
{
    static void Main(string[] args)
    {
        CauseStackOverflow();
    }

    static void CauseStackOverflow()
    {
        CauseStackOverflow();	
    }
}

The program will terminate after encountering a StackOverflowException.

image

However, if you compile the same program targeting the x64 platform in release mode, and run it from your desktop (not from Visual Studio which attaches a debugger), the program keeps running. The StackOverflowException is not thrown and the program never terminates.

After some investigation, it turns out that the JIT compiler on the x64 will perform tail call optimization for such code and so will never overflow the stack!

These blog posts by David Broman go into detail on tail call optimization in the CLR.

If I create a condition that prevents the optimization like modifying the recursed method to return a value type:

class Program
{
    static void Main(string[] args)
    {
        CauseStackOverflow();
    }

    static int CauseStackOverflow()
    {
        return CauseStackOverflow();
	
    }
}

The StackOverflowException occurs on the x64 platform and the process terminates as expected.

Loading