C# Catch a Stack Overflow Exception

C# catch a stack overflow exception

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)

*"hosted environment" as in "my code hosts CLR and I configure CLR's options" and not "my code runs on shared hosting"

How to handle a StackOverflowException

According to MSDN:

Starting with the .NET Framework 2.0, you can’t catch a StackOverflowException object with a try/catch block, and the corresponding process is terminated by default. Consequently, you should write your code to detect and prevent a stack overflow.

In this case, it means you should actively prevent the exception by passing in a integer checking if the depth gets to low and throw an exception yourself, something like this:

public string Recursive(int value, int counter)
{
if (counter > MAX_RECURSION_LEVEL) throw new Exception("Too bad!");

Recursive(value, counter + 1);
return string.Format("You entered: {0}", value);
}

Or rewrite the algorithm to use tail recursion.

Can't handle StackOverflowException C#

You cannot handle a stack overflow exception because one of the things the code has to do in order to record information about an exception is to call some code.

Since you have overflowed the stack, one of the things it absolutely cannot do is call more code.

Hence why Windows just terminates the program.

A StackOverflowException is thus uncatchable, unless you explicitly throw it yourself before the actual stack actually overflow.

Now, that answers the question you asked.

The real problem here is that the code as shown does not in fact call itself, but the name of the method _SelectedIndexChanged means that something in that code makes the checkedListBox1 call this method again.

It probably shouldn't.

You should place a breakpoint inside this method and hit F5 a couple of times and inspect the call stack to see which statement inside is causing this to happen.

There is another reason why this might happen and I can best describe it by referring to a full glass of water. If you have a glass of water that is already full (but has not yet overflowed) and you put one extra drop into the glass, and then it overflows, was it that one single drops fault, or was it all the billion of other drops that were put into the glass before it?

There might be something completely different that is causing the stack overflow to happen, it just so happens this method is the very last drop that overflowed the stack.

Try the breakpoint, see how far you get.

My code throws stackoverflowexception when i execute

Why does StackOverflowException occur?

StackOverflowException occurs because of the infinite recursion inside the constructor of the Masterpage.

Lets consider how this recursion occurs. BookEditor inherits Masterpage. (The following conclusions are also applicable to the other inheritors of the Masterpage). I suspect that BookEditor has a single constructor without parameters BookEditor(). In C# if you call constructor without parameters of the derived type it by default calls constructor without parameters of the base type (if you don't explicitly specify other constructor of the base type). Lets assume that we want to create an instance of the Masterpage. We call its constructor Masterpage(). Inside it we call constructor of the BookEditor. But BookEditor inherits Masterpage and therefore it calls constructor of the Masterpage. Constructor of the Masterpage again calls constructor of the BookEditor and etc. These sequence of the constructor calls leads to the infinite recursion and StackOverflowException as a result.


How should you fix this problem?

I think that more information is needed to thoroughly answer this question.

As a workaround you should create inheritors of the Masterpage outside of its constructor:

public partial class Masterpage : Form
{
private readonly IEnumerable<Form> _forms;

public Masterpage()
{
InitializeComponent();
}

// Now we set forms here, not in the constructor.
public void SetForms(IEnumerable<Form> forms)
{
_forms = forms;
}

private void showForm(Form f)
{
foreach (Form form in _forms)
form.Hide();

this.Hide();
f.Show();
}

// Other members of the Masterpage.
...
}

// Palce this code where you create and show Masterpage.
var bookE = new BookEditor();
var studentE = new StudentEditor();
var viewB = new ViewBorrowedBooks();
var issueBook = new IssueBook();

var forms = new List<Form> {bookE, studentE, viewB, issueBook};
bookE.SetForms(forms);
studentE.SetForms(forms);
viewB.SetForms(forms);
issueBook.SetForms(forms);

var masterPage = new Masterpage();
masterPage.SetForms(forms);

StackOverflow Exception from get and set


public DateTime time
{
get { return this.time; }
set
{
this.time = value;
}
}

you aren't using backing fields, but setting the property itself from within the property setter.

You can fix this by using 1) an auto property

public DateTime Time { get; set; }

or 2) a backing field

private DateTime _time;
public Datetime Time
{
get { return _time; }
set { _time = value; }
}

they both equate to the same code.

For an explanation, when you get time in your code:

get { return this.time; } 

it has to retrieve the value of time to return. It does that by calling the get on time, which has to get retrieve the value of time, etc.

How is a StackOverflowException detected?

Stack overflows

I'll make it easy for you; but this is actually quite complex... Note that I will generalize quite a bit here.

As you might know, most languages use the stack for storing call information. See also: https://msdn.microsoft.com/en-us/library/zkwh89ks.aspx for how cdecl works. If you call a method, you push stuff on the stack; if you return, you pop stuff from the stack.

Note that recursion isn't normally 'inlined'. (Note: I explicitly say 'recursion' here and not 'tail recursion'; the latter works like a 'goto' and doesn't grow the stack).

The easiest way to detect a stack overflow is to check your current stack depth (e.g. bytes used) - and if it hits a boundary, give an error. To clarify about this 'boundary check': the way these checks are done is normally by using guard pages; this means boundary checks aren't normally implemented as if-then-else checks (although some implementations exist...).

In most languages, each thread has its own stack.

Detecting infinite loops

Well now, here's a question I haven't heard for a while. :-)

Basically detecting all infinite loops requires you to solve the Halting Problem. Which is by the way an undecidable problem. This is definitely not done by compilers.

This doesn't mean you can't do any analysis; in fact, you can do quite a bit of analysis. However, also note that sometimes you want things to run indefinitely (such as the main loop in a web server).

Other languages

Also interesting... Functional languages use recursion, so they are basically bound by the stack. (That said, functional languages also tend to use tail recursion, which works more or less like a 'goto' and don't grow the stack.)

And then there's Logical languages.. well now, I'm not sure how to loop forever in that - you'll probably end up with something that won't evaluate at all (no solution can be found). (Though, this probably depends on the language... )

Yielding, async, continuations

An interesting concept is you might think of is called continuations. I've heard from Microsoft that when yield was first implemented, real continuations were considered as implementation. Continuations basically allow you to 'save' the stack, continue somewhere else and 'restore' the stack back at a later point... (Again, the details are much more complicated than this; this is just the basic idea).

Unfortunately Microsoft didn't go for this idea (although I can imagine why), but implemented it by using a helper class. Yield and async in C# work by adding a temporary class and interning all the local variables within the class. If you call a method that does a 'yield' or 'async', you actually create a helper class (from within the method you call and push on the stack) that's pushed on the heap. The class that's pushed on the heap has the functionality (e.g. for yield this is the enumeration implementation). The way this is done is by using a state variable, which stores the location (e.g. some state id) where the program should continue when MoveNext is called. A branch (switch) using this ID takes care of the rest. Note that this mechanism does nothing 'special' with the way the stack works itself; you can implement the same by yourself using classes and methods (it just involves more typing :-)).

Solving stack overflows with a manual stack

I always like a good flood fill. A picture will give you a hell of a lot of recursion calls if you do this wrong... say, like this:

public void FloodFill(int x, int y, int color)
{
// Wait for the crash to happen...
if (Valid(x,y))
{
SetPixel(x, y, color);
FloodFill(x - 1, y, color);
FloodFill(x + 1, y, color);
FloodFill(x, y - 1, color);
FloodFill(x, y + 1, color);
}
}

There's nothing wrong with this code though. It does all the work, but our stack gets in the way. Having a manual stack solves this, even though the implementation is basically the same:

public void FloodFill(int x, int y, int color)
{
Stack<Tuple<int, int>> stack = new Stack<Tuple<int, int>>();
stack.Push(new Tuple<int, int>(x, y));
while (stack.Count > 0)
{
var current = stack.Pop();

int x2 = current.Item1;
int y2 = current.Item2;

// "Recurse"
if (Valid(x2, y2))
{
SetPixel(x2, y2, color);
stack.Push(new Tuple<int, int>(x2-1, y2));
stack.Push(new Tuple<int, int>(x2+1, y2));
stack.Push(new Tuple<int, int>(x2, y2-1));
stack.Push(new Tuple<int, int>(x2, y2+1));
}
}
}

StackOverflowException on Getter C#

This line in SnakeGame causes a recursion

public readonly Movement Movement = new Movement(SenseHat);

Since Movement is inherited from SnakeGame, its constructor will initialize SnakeGame, calling the line above again to initialize its own Movement field. That results into recursion.

How to find the source of a StackOverflowException in my application

This is typically something I use WinDbg to track down, otherwise it's just a guessing game. Here's a quick walkthrough that should set you in the right direction.

WinDbg is a debugger for Windows, good for debugging managed and unmanaged code. It's also great for examining crash dumps. Let's start with an example program.

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

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
static int IWillStackOverflow(int i)
{
return IWillStackOverflow(i + 1);
}
}

This is a pretty contrived example, but let's roll with it. It does indeed stack overflow, and nor does it provide a stacktrace. This is where WinDbg comes in. First you need to install it, which is part of the Debugging Tools in the Windows SDK. There are two versions, the x64 and x86. You'll want to run the one that matches the bitness of your application.

In WinDbg, use File -> Open Executable and run your executable with WinDbg attached. The debugger will break as soon as your application loads, you can use the g command to Go and use your application until you get a StackOverflowException. Before you do that though, make sure your symbols are correct - usually running .symfix+ will correct it, then you can go.

When you get your StackOverflowException, the debugger will break on the thread that raised the exception, and the message will be something like this:

(cc0.b00): Stack overflow - code c00000fd (first chance)

Now we can load the managed debugging extensions with this command (I am assuming you are using the .NET Framework 4.0 or 4.5 here):

.loadby sos clr

And calling !clrstack. In this example, the output is:

000000d440c76040 00007ffb282b0111 StackOverflower.Program.IWillStackOverflow(Int32) [Program.cs @ 20]
000000d440c76080 00007ffb282b0111 StackOverflower.Program.IWillStackOverflow(Int32) [Program.cs @ 20]
000000d440c760c0 00007ffb282b0111 StackOverflower.Program.IWillStackOverflow(Int32) [Program.cs @ 20]
..Repeat thousands of times..

So we have our managed stack at the time of the StackOverflowException.

If your Application doesn't StackOverflow very easily, you can configure ADPlus to take a memory dump of your application at the time of the StackOverflowException. ADPlus is another big-hammer tool, but it's effective. First you need a configuration for ADPlus, here is an example one:

<ADPlus> 
<!-- Add log entry, log faulting thread stack and dump full on first chance StackOverflow -->
<Exceptions>
<Config>
<!-- Use sov for stack overflow exception -->
<Code> sov </Code>
<Actions1> Log;Stack;FullDump </Actions1>
<!-- Depending on what you intend - either stop the debugger (Q or QQ) or continue unhandled (GN) -->
<ReturnAction1> GN </ReturnAction1>
< Config>
</Exceptions>
</ADPlus>

This configuration example was originally published by user jaskis on the MSDN Forums: http://blogs.msdn.com/b/jaskis/archive/2010/08/11/cwa-ends-up-with-blank-screen-on-browser-on-iis-7.aspx
Then use the command line to start your application with the configuration.


This is just an example, WinDbg is a very powerful tool, though it has a bit of a learning curve. There are a lot of good resources on the internet for getting the hang of it. Tess Ferrandez has many articles in her blog that cover WinDbg and the managed debugging extensions.



Related Topics



Leave a reply



Submit