2

I have a large, complex C# GUI application which is crashing in a completely reproducible way, but I cannot easily diagnose the cause of the crash because rather than breaking the debugger with a call stack in the usual way, the debugging session completely exits.

The only hint is that there's a message at the end of the output window: STATUS_STACK_BUFFER_OVERRUN.

I am painstakingly trying to put breakpoints in at random places before the crash happens, trying to gradually get my breakpoints closer to where the problem happens, but this approach is not getting me anywhere quickly.

I'm wondering if there are any existing tools which work sort of like an instrumenting profiler, basically observing and logging all of the function enters and exits, so that when the program crashes with a corrupted stack, it's still possible to examine this external data to determine where execution was last happening?

I don't expect that this is a feature that most performance-oriented profilers have, since they are more concerned with how many times a function was called and for how long, but perhaps there's a tool which will tell me exactly what the last known running piece of code was?

I'm open to other suggestions if there's a way to solve/diagnose this within Visual Studio or using other techniques.

uglycoyote
  • 1,555
  • 1
  • 19
  • 25
  • As a post-mortem, I did not find any tool which fit the bill, so I solve the problem the hard way -- lots of guessing, second guessing, print statements and breakpoints to figure out where it was failing. The cause in my case was a stack-allocated buffer (locally declared array of 4x4 matrices) which was not sufficiently large, and the code was writing past the end of that and ruining the rest of the stack. – uglycoyote Jan 24 '18 at 20:40

3 Answers3

1

You can use a conditional breakpoint to trigger when the stack depth exceeds a certain value:

(new StackTrace()).GetFrames().Length > 60

The trick here is knowing where to put the breakpoint, as it has to be set somewhere in the recursive cycle. But if you know what triggers the error you might have enough intuition to choose some strategic places to put the check. You can also use a process of elimination: if the breakpoint isn't triggered, you know that code is not involved in the cycle.

Also note that the conditional breakpoint is costly and will significantly slow down the application being debugged. If you're not opposed to littering your code with debugging statements, you can call Debugger.Break() instead of setting breakpoints:

if (Debugger.IsAttached && (new StackTrace()).GetFrames().Length > 60)
    Debugger.Break();
TypeIA
  • 16,916
  • 1
  • 38
  • 52
  • 1
    Although the STACK_BUFFER_OVERRUN error makes it sound like the kind of thing that would be caused by runaway recursion, I'm not certain that anything like that's going on. (typically when you blow the stack by recursing too many times you still see the call stack in Visual Studio). It seems more like some random piece of code is just coming along and trashing the stack without it necessarily being a deep call stack. – uglycoyote Jan 24 '18 at 18:51
  • @uglycoyote Unless you have some unmanaged code running in the same process you shouldn't be suffering from stack/heap corruption. Not saying it can't happen but the managed environment is very robust against such a thing. – TypeIA Jan 24 '18 at 19:58
  • Ah, yes, good of you to point out. It was in fact unmanaged code where the problem was occurring. I should have specified that as part of the problem description perhaps. It's a C# GUI that uses some C++/CLI and unmanaged C++ under the hood to do 3D animation. – uglycoyote Jan 25 '18 at 18:21
0

STATUS_STACK_BUFFER_OVERRUN means that someone blew passed the end or beginning of their stack variables, most likely in unmanaged or interop code.

If you attach the debugger in native mode or mixed mode, go to the Exceptions window and add a Win32 exception with the code 0xc0000409 (stack overflow). If you trigger the error, it should break in the debugger.

Kristof
  • 104
  • 4
0

You can use my Runtime Flow tool to log all function calls in your application. After a crash you can see what was the last function enter.

Sergey Vlasov
  • 26,641
  • 3
  • 64
  • 66