How to Prevent And/Or Handle a Stackoverflowexception

How do I prevent and/or handle a StackOverflowException?

From Microsoft:

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.

I'm assuming the exception is happening within an internal .NET method, and not in your code.

You can do a couple things.

  • Write code that checks the xsl for infinite recursion and notifies the user prior to applying a transform (Ugh).
  • Load the XslTransform code into a separate process (Hacky, but less work).

You can use the Process class to load the assembly that will apply the transform into a separate process, and alert the user of the failure if it dies, without killing your main app.

EDIT: I just tested, here is how to do it:

MainProcess:

// This is just an example, obviously you'll want to pass args to this.
Process p1 = new Process();
p1.StartInfo.FileName = "ApplyTransform.exe";
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

p1.Start();
p1.WaitForExit();

if (p1.ExitCode == 1)
Console.WriteLine("StackOverflow was thrown");

ApplyTransform Process:

class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
throw new StackOverflowException();
}

// We trap this, we can't save the process,
// but we can prevent the "ILLEGAL OPERATION" window
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.IsTerminating)
{
Environment.Exit(1);
}
}
}

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.

How to prevent StackoverflowException in my C# code

Something like

string pageToken=null;
do {
pageToken = Getdata(info, pageToken):
} while (pageToken != null)

how to avoid or handle stack overflow exception in C#?

You are using recursion, recursion needs an end condition to stop the recursion. If not you will trigger a stackoverflow exception. Check your end condition on if it is valid in the case you are testing. You can handle all reclusive functions in a non recursive function, however I guess that you are just missing the end/exit condition.

You have to take into account the places you already know. At this moment you are rechecking them over and over again.

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.

How to prevent Third Party DLL's StackOverflow Exception from killing Main Application?

The short answer here is "no"; a stack-overflow scenario cannot be reliably caught / recovered from.

  • make sure you're on the most recent version available (it might be fixed!)
  • see whether the documentation lists this as a known issue with possible workaround
  • if it is a paid product, ask them to fix it as part of your support
  • if it is open source, consider fixing it yourself and contributing the fix

If none of these are possible, then the fallback would be to write a second executable that just does this processing (using either IPC or file-based means to get data to/from the second process) - then spawn that second process in the knowledge that if it explodes, only the child process has been burned.

Prevent System.StackOverflowException when recursively calling a method

The stack overflow is occurring because zeroReveal is recursively calling itself forever. To fix this we need to find ways where we do not need it to make further calls to itself.

The name of the method gives us a clue. If the square has already been revealed, then surely the method does not need to do anything, since it has already been revealed.

It looks like the button's Text property is an empty string if it has not yet been revealed. So change the foreach so that it doesn't process squares that have already been revealed:

foreach (Square s in list)
{
if (s.getButton().Text == ""))
{
// existing code in the foreach loop goes here
}
}

How to overcome StackOverflowException bypassing unhandled exception handling in .NET

There are three kind of so-called "asynchronous exceptions". That are the ThreadAbortException, the OutOfMemoryException and the mentioned StackOverflowException. Those excepions are allowed to occur at any instruction in your code.

And, there's also a way to overcome them:

The easiest is the ThreadAbortException. When the current code executes in a finally-block. ThreadAbortExceptions are kind of "moved" to the end of the finally-block. So everything in a finally-block can't be aborted by a ThreadAbortException.

To avoid an OutOfMemoryException, you have only one possibility: Do not allocate anything on the Heap. This means that you're not allowed to create any new reference-types.

To overcome the StackOverflowException, you need some help from the Framework. This help manifests in Constrained Execution Regions. The required stack is allocated before the actual code is executed and additionally also ensures that the code is already JIT-Compiled and therefor is available for execution.

There are three forms to execute code in Constrained Execution Regions (copied from the BCL Team Blog):

  • ExecuteCodeWithGuaranteedCleanup, a stack-overflow safe form of a try/finally.
  • A try/finally block preceded immediately by a call to RuntimeHelpers.PrepareConstrainedRegions. The try block is not constrained, but all catch, finally, and fault blocks for that try are.
  • As a critical finalizer - any subclass of CriticalFinalizerObject has a finalizer that is eagerly prepared before an instance of the object is allocated.

    • A special case is SafeHandle's ReleaseHandle method, a virtual method that is eagerly prepared before the subclass is allocated, and called from SafeHandle's critical finalizer.

You can find more at these blog posts:

Constrained Execution Regions and other errata [Brian Grunkemeyer] at the BCL Team Blog.

Joe Duffy's Weblog about Atomicity and asynchronous exception failures where he gives a very good overview over asynchronous exceptions and robustness in the .net Framework.

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));
}
}
}


Related Topics



Leave a reply



Submit