Reputation: 1892
Scenario:
I've just been on a roll and implemented a bunch of code, but when I execute it I get thrown a StackOverflowException
? The StackOverflowException
doesn't have a stacktrace so I'm stuck. I know why a stack overflow might occur, but to fix it I need to know where it's root is.
All I'm getting is:
An unhandled exception of type 'System.StackOverflowException' occurred in tag-you're-it.dll
Options:
PS:
This is a hypothetical situation (although not too uncommon) and therefore no code is available.
Upvotes: 47
Views: 35456
Reputation: 5939
The ProcDump utility has helped us to debug the issue as described in details here. Steps:
procdump -accepteula -e 1 -f C00000FD.STACK_OVERFLOW -g -ma <process ID> d:\home\DebugTools\Dumps
(the directory must exist)We can use the same technique on Azure by enabling the CrashDiagnoser extension, like described here. Basically it performs the same steps as above. The dump file it generates could be downloaded and opened within the Visual Studio.
Upvotes: 7
Reputation: 1486
During the course of the development of IKVM.MET, I figured out a trick to debug stack overflow bugs in both static and dynamic assemblies, since IKVM.NET makes extensive use of dynamic assemblies. I would run the executable in the Visual Studio debugger, and when a stack overflow occurs, the Visual Studio debugger would suspend the process, instead of terminating it. Then, I used dotnet-dump to obtain a core dump, and finally, I would terminate the process to free up RAM and analyze the core dump using dotnet-dump. Note that this only works on .NET core applications.
Command to create the core dump
dotnet-dump collect -p <Process ID here>
The process ID can be obtained using the Task Manager. Command to view the stack trace:
dotnet-dump analyze <file name of dump> -c clrstack -all
How to use dotnet-dump, if you want to do further debugging
Note: This debugging technique is risky, since the process could be corrupted, and may not work every single time.
Upvotes: 0
Reputation: 13233
WinDbg can get the job done, including even getting a sensible (clr) stack trace. You'll need to get WinDbg unless you've already installed it with Visual Studio or Windows SDK. Note: "WinDbg Preview" with the new GUI has worked fine for me.
I suggest to start your process from WinDbg, but of course you can also attach it to a running process if this suits you better.
Note: Right after starting the process, the CLR is not loaded, and .loadby SOS.dll clr
will fail ("unable to find module 'clr'). You have to wait for the CLR to be loaded. To stop execution once that happens perform:
sxe ld clr
Once the CLR is loaded you'll have to perform the following steps to break on StackOverflowException
(enter in the command window / line):
.loadby SOS.dll clr
(not .loadby sos clr
—this can lead to the extension being loaded twice)!stoponexception -create System.StackOverflowException
g
(continues debugging)trigger the StackOverflowException / wait for it to happen
!clrstack
(will print the stacktrace)Notable sources:
Upvotes: 32
Reputation: 71
I suspect if the stack size of the thread that caused the stack overflow is larger than some threshold that Visual Studio debugger can track, then the call stack is unavailable.
A workaround is to spawn a thread who's stack size is smaller than the default stack size, thus Visual Studio debugger can track the call stack.
(new Thread(delegate ()
{
ProduceAStackOverFlowHere() ;
}, 256 * 1024)).Start();//Default size for 32 bit process is 1MB, 64 bit process is 4MB. So I'll set the size at 256KB.
Upvotes: 3
Reputation: 4247
Just wanted to add to the answer about using WinDbg, with what I found for debugging a dotnet core application
.loadby sos coreclr
(this should detect the version of .net core that you are using, but if not you can use .load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.0.5\sos
where 2.05 is the version of .netcore you are using!help
!dso
to get a dump of the stack In my case that told me exactly where the stackoverflow exception was occurring
Upvotes: 1
Reputation: 351
Personally, I like to narrow it down as much as possible to a certain section of code. For example, I just had one. The odd thing was it was only happening on the machine I couldn't directly debug.
I had two threads running in parallel, so I stopped one from running(or you could unparallelize it).
Then I went through my functions and added like print out functions, such as: Just as function starts:
Console.WriteLine("<Enter method: {0}", DebuggingHelper.GetCurrentMethod());
Just before function returns:
Console.WriteLine(">Exit method: {0}", DebuggingHelper.GetCurrentMethod());
Where GetCurrentMethod is defined as:
[MethodImpl(MethodImplOptions.NoInlining)]
public static string GetCurrentMethod()
{
StackTrace st = new StackTrace();
StackFrame sf = st.GetFrame(1);
return sf.GetMethod().Name;
}
Then I run it, maybe I don't add to all functions, but enough to narrow down where in the code it's happening. Then within that section, add more.
You could also add checkpoint as it runs through certain methods.
Then run it again, what you'll find is that the StackOverFlow exception will occur between those statements. Keep narrowing down till you find it.
Fairly simply and quick to find where it's happening this way.
Upvotes: 1
Reputation: 3632
If you have the code and are able to run your program from Visual Studio it should break in the debugger (if first-chance exceptions are enabled) when it encounters the System.StackOverflowException. From there you can examine the call stack and see which calls are blowing the stack.
I've confirmed that this works for Visual Studio 2010 and Visual C# 2010 Express.
Upvotes: 0
Reputation: 115
Go to Debug, exceptions and check the thrown checkbox at 'Common Language Runtime Exceptions'. Now when you cause the stackoverflow exception, the debugger will stop (eventually) and show you the call stack.
Upvotes: 7
Reputation: 42125
This is almost always due to recursion. Either a method calling itself, or a method calling a method that calls it back and so on.
To find it:
StackOverflowException
(I guess something to do with not being able to catch one, either). However there are ways to get a dump as mentioned here.Occasionally you'll get typos like this, too:
private string name;
public string Name
{
get { return Name; } // Ooops! This is recursive, all because of a typo...
}
Which is one reason why I personally now prefer to use automatic properties.
Upvotes: 17
Reputation: 2198
You can execute the program on debug mode and pause it. On the current callstack you can see that there are a method or a group of method that appears several times, these are the problematic methods. Put a break point on this method and look what its calling itself all the time.
Upvotes: 5
Reputation: 116674
At the method that is the "entry point" to the operation that fails, put a breakpoint. Step through the code and watch for occurrences of the same sequence of method calls happening over and over in an identical pattern so the call stack gets deeper and deeper.
As soon as you notice that, put a breakpoint at the current location, wherever that is. Continue execution (F5 in Visual Studio) - if you're on the right track then the debugger will stop very quickly at the same location, and the call stack will be even deeper.
Now you have a "live" stack frame you can examine, in order to figure out how to ensure that this recursion will properly terminate.
Upvotes: 1