Can I prevent StackOverflowException from crashing my debuggee in Visual Studio? - c#

I'm debugging a 3rd party library that is littered with properties that occasionally throw StackOverFlowException.
Whenever I look at objects from this library in the Watch window, I end up getting the error message "Function evaluation was aborted" and the app I'm debugging crashes.
I wrote an example of a property that reproduces this (when trying to evaluate it in the Watch window):
private static int CausesStackoverflow
{
get { return CausesStackoverflow; }
}
Is there any way to evaluate properties in the Watch window without risking my app crashing due to a Stackoverflow?

You should prevent (using counters or other tricks) and not catch StackOverflowExceptions.
Since this is 3rd party code (so I suppose it can't be changed) you can try this:
Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.
The CLR is being run in a hosted environment where the host specifically allows for StackOverflow exceptions to be handled
The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
From MSDN StackOverflowException page:
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.

Related

How to programmatically take control over a StackOverflow exception caused by an endless recursive method call or an infinite loop?

According to
C# catch a stack overflow exception
How to debug a stackoverflowexception in .NET
at the moment it's not possible to catch StackOverflowException programmatically, but I was wondering if it's possible to use debugger api (Debug or Debugger) and react to stack overflow exception?
Has anyone done something similar?
You can monitor your current call stack framecount using System.Diagnostics.Stacktrace.FrameCount. No way to determine the max framecount however, but if this number gets up very high you can bet you'll get in trouble soon.
A Stack Overflow caused by an endless recursive method call or an infinite loop actually saturates the stack of the current processus which leads to an unrecoverable process crash like a bulldozer that has crushed the entire alley of trees.
It is then impossible for the current process to catch this exception which goes out of the context of the process that lost the control and "does not exist anymore", and then only a debugger or a host application as explained in the link you provided can retrieve this information.
Nothing can be done at this point.
So before Windows 95 and especially NT, a stack overflow in a process usually and relentlessly caused a system crash because the processes were not isolated, not being in protected mode, and they crushed the whole land.
https://www.tutorialspoint.com/operating_system/os_processes.htm
Stack overflow
Protected virtual address mode
So you can't use a debugger API.
But you can write a special host that runs your app and controls it like the debugger do, perhaps for example:
Hosting EXE Applications in a WinForm project (CodeProject)
Creating a host application for the .NET Common Language Runtime (CodeProject)
Using HostBuilder and the Generic Host in .NET Core Microservices
.NET Generic Host

Does an appcrash with a STATUS_STACK_OVERFLOW in a .Net application mean the stack overflow occured in native code?

I get an appcrash with execution code c00000fd (STATUS_STACK_OVERFLOW) in ntdll.dll.
Does that mean there was a stack overflow somewhere in native code, outside my managed code? Because for managed code, we have System.StackOverflowException. But there is none in my case, and no stack trace that could provide a clue.
You cant catch System.StackOverflowException any more
Starting with .Net 2.0 they can only be caught in the following
circumstances.
The CLR is being run in a hosted environment where the host specifically allows for StackOverflow exceptions to be handled
The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
Although the error says it occurred in ntdll.dll it is most likely caused form your code.
My first steps would be to add, or turn on your highest debug logging in production, so you can try to narrow down where it's happening and the circumstances.
Second I'd start debugging (attaching the debugger) and scrutinising that method class until you find it. Most likely it's due to some recursion, that's the first place I'd start looking.
Additional Resources and references
C# catch a stack overflow exception
How to find the source of a StackOverflowException in my application
How to debug System.StackOverflowException without link to source code?
How do I prevent and/or handle a StackOverflowException?
How to debug a stackoverflowexception in .NET
Troubleshooting Exceptions: System.StackOverflowException
StackOverflowException Class
In the .NET Framework 1.0 and 1.1, you could catch a
StackOverflowException object (for example, to recover from unbounded
recursion). 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. For
example, if your app depends on recursion, use a counter or a state
condition to terminate the recursive loop.

Stackoverflow.. literally.. on azure [duplicate]

I have a recursive call to a method that throws a stack overflow exception. The first call is surrounded by a try catch block but the exception is not caught.
Does the stack overflow exception behave in a special way? Can I catch/handle the exception properly?
Not sure if relevant, but additional information:
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(...)
Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.
The CLR is being run in a hosted environment* where the host specifically allows for StackOverflow exceptions to be handled
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"
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. ;)
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.
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, you need to open Exception Settings from the 'Debug' menu. In older versions of Visual Studio, this is at 'Debug' - 'Exceptions'; in newer versions, it's at 'Debug' - 'Windows' - 'Exception Settings'.
Once you have the settings open, 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.
As mentioned above several times, it's not possible to catch a StackOverflowException that was raised by the System due to corrupted process-state. But there's a way to notice the exception as an event:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Starting with the .NET Framework version 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
Nevertheless your application will terminate after exiting the event-function (a VERY dirty workaround, was to restart the app within this event haha, havn't done so and never will do). But it's good enough for logging!
In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug. For more information, including a list of cases in which the runtime does not terminate, see Exceptions in Managed Threads.
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
You can't. The CLR won't let you. A stack overflow is a fatal error and can't be recovered from.
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.
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.

C# stack overflow is not able to be handled [duplicate]

I have a recursive call to a method that throws a stack overflow exception. The first call is surrounded by a try catch block but the exception is not caught.
Does the stack overflow exception behave in a special way? Can I catch/handle the exception properly?
Not sure if relevant, but additional information:
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(...)
Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.
The CLR is being run in a hosted environment* where the host specifically allows for StackOverflow exceptions to be handled
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"
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. ;)
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.
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, you need to open Exception Settings from the 'Debug' menu. In older versions of Visual Studio, this is at 'Debug' - 'Exceptions'; in newer versions, it's at 'Debug' - 'Windows' - 'Exception Settings'.
Once you have the settings open, 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.
As mentioned above several times, it's not possible to catch a StackOverflowException that was raised by the System due to corrupted process-state. But there's a way to notice the exception as an event:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Starting with the .NET Framework version 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
Nevertheless your application will terminate after exiting the event-function (a VERY dirty workaround, was to restart the app within this event haha, havn't done so and never will do). But it's good enough for logging!
In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug. For more information, including a list of cases in which the runtime does not terminate, see Exceptions in Managed Threads.
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
You can't. The CLR won't let you. A stack overflow is a fatal error and can't be recovered from.
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.
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.

Is there any way to print any extended information on StackOverflowException?

One of my clients reported that the software I develop terminates unexpectedly. In app log, the only text available is Process is terminated due to StackOverflowException. There is no more information which would help me diagnose and fix it.
Is there any way to get the location where the exception was thrown? VS breaks on StackOverflowException, but is there any feasible method of diagnosing it without running the application in the debugger (or looking for it in all methods which contain recursion)?
You cannot normally execute any code after a stack overflow, it's one of the rare uncatchable fatal exceptions, so you cannot simply catch it to log any extended details.
The only way you could work around that is by tracking the exceptions from outside of the code that has a stack overflow. You would need to create a native code application to hosts the CLR. If you do that, you can specify that StackOverflowException is not 100% fatal. This is briefly mentioned on the StackOverflowException MSDN page:
If your app hosts the common language runtime (CLR), it can specify that the CLR should unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface.
But even that would still mean that a simple try...catch is not sufficient to actually catch the exception. You would have to make sure that the exception handling is not done from the app domain that has a stack overflow. It might be done from a different app domain, or it might be done from unmanaged code.

Categories

Resources