views:

1620

answers:

9

Hello,

I got a recursive call to a methode that throw a stack overflow exception. The first call is surrounded by a try catch block but the exception is not caught.

Do the stack overflow exception behave in a special way ? Can I catch/handle properly the exception ?

NB : if relevant :

  • the exception is not thrown in the main thread

  • the object where the code is throwing the exception is manually loaded by Assembly.LoadFrom(...).CreateInstance(...)

+3  A: 

Yes from CLR 2.0 stack overflow is considered a non-recoverable situation. So the runtime still shut down the process.

For details please see the documentation http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx

Brian Rasmussen
+10  A: 

From the MSDN page on StackOverflowExceptions:

In prior versions of the .NET Framework, your application could catch a StackOverflowException object (for example, to recover from unbounded recursion). However, that practice is currently discouraged because significant additional code is required to reliably catch a stack overflow exception and continue program execution.

Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop. Note that an application that hosts the common language runtime (CLR) can specify that the CLR unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface and Hosting the Common Language Runtime.

Damien_The_Unbeliever
+3  A: 

You can't. The CLR won't let you. A stack overflow is a fatal error and can't be recovered from.

Matthew Scharley
+19  A: 

Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.

  1. The CLR is being run in a hosted environment where the host specifically allows for StackOverflow exceptions to be handled
  2. The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
JaredPar
If it can't be caught in any relevant scebario, why does the StackoverflowException object exist?
Manu
@Manu for at least a couple of reasons. 1) Is that it could be caught, kind of, in 1.1 and hence had a purpose. 2) It can still be caught if you are hosting the CLR so it's still a valid exception type
JaredPar
+2  A: 

It's impossible, and for a good reason (for one, think about all those catch(Exception){} around).

If you want to continue execution after stack overflow, run dangerous code in a different AppDomain. CLR policies can be set to terminate current AppDomain on overflow without affecting original domain.

ima
A: 

I suggest StackOverflowHandler() as the name of the function that you would call to handle the exception.

Sorry, couldn't resist... :-D

Serge - appTranslator
+1  A: 

As several users have already said, you can't catch the exception. However, if you're struggling to find out where it's happening, you may want to configure visual studio to break when it's thrown.

To do that, choose 'Exceptions' from the Debug menu, expand 'Common Language Runtime Exceptions', expand 'System', scroll down and check 'System.StackOverflowException'. Then you can look at the call stack and look for the repeating pattern of calls. That should give you an idea of where to look to fix the code that's causing the stack overflow.

Simon
+8  A: 

The right way is to fix the overflow, but....

You can give yourself a bigger stack:-

using System.Threading;
Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();

You can use System.Diagnostics.StackTrace FrameCount property to count the frames you've used and throw your own exception when a frame limit is reached.

Or, you can calculate the size of the stack remaining and throw your own exception when it falls below a threshold:-

class Program
{
    static int n;
    static int topOfStack;
    const int stackSize = 1000000; // Default?

    // The func is 76 bytes, but we need space to unwind the exception.
    const int spaceRequired = 18*1024; 

    unsafe static void Main(string[] args)
    {
        int var;
        topOfStack = (int)&var;

        n=0;
        recurse();
    }

    unsafe static void recurse()
    {
        int remaining;
        remaining = stackSize - (topOfStack - (int)&remaining);
        if (remaining < spaceRequired)
            throw new Exception("Cheese");
        n++;
        recurse();
    }
}

Just catch the Cheese. ;)

JonB
A: 

You can't as most of the posts are explaining, let me add another area:

On many websites you will find people saying that the way to avoid this is using a different AppDomain so if this happens the domain will be unloaded. That is absolutely wrong (unless you host your CLR) as the default behavior of the CLR will raise a KillProcess event, bringing down your default AppDomain.

No hay Problema