There has been discussion here before about the correct way to rethrow an exception. This question, instead, is about how to get useful behavior from Visual Studio when using rethrow.
Consider this code:
static void foo() {
throw new Exception("boo!");
}
static void Main(string[] args) {
try {
foo();
} catch (Exception x) {
// do some stuff
throw;
}
}
The exception that comes out has the correct stack trace, showing foo() as the source of the exception. However, the GUI Call Stack window only shows Main, whereas I was expecting it to show the exception's call stack, all the way to foo.
When there is no rethrow, I can use the GUI to very quickly navigate the call stack to see what call caused the exception and how we got there.
With the rethrow I'd like to be able to do the same thing. Instead, the call stack that the GUI shows is of no use to me. I have to copy the exception details to the clipboard, paste it to Notepad, and then manually navigate to whichever function of the call stack I'm interested in.
By the way, I get the same behavior if I add [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
or if I change the catch to just catch (Exception)
.
My question is: given that the code I have uses rethrow, can someone suggest a convenient way to navigate the call stack associated with the exception? I'm using Visual Studio 2010.
If you use ReSharper, you can copy exception stacktrace to clipboard, then choose in the menu: ReSharper > Tools > Browse Stack Trace (Ctrl+E,T). It will show stacktrace with clickable locations, so you'll be able to quickly navigate.
(source: jetbrains.com)
This feature is also very useful while digging through logs from users (if stacktraces of exceptions are logged).
Not that you should re-throw but here's a blog post about how to preserve the stack trace, essentially it boils down to this:
The debugger breaks at the
throw
inMain
because that exception is unhandled. By default, the debugger will only break on unhandled exceptions. Once you've stopped atMain
, the call stack for the original exception fromfoo
is present in the exception, but all of the other context has been lost (e.g. locals, stack/memory state).It sounds like you want the debugger to break on the
throw
infoo
, so you should tell the debugger to break on first-chance exceptions:In this case, the debugger will break immediately when
foo
throws an exception. Now, you can examine the stack, locals, etc., in the context of the original exception. If you continue execution (F5), the debugger will break again on the rethrow inMain
.Taking another approach, if you're running VS2010 Ultimate, you can also use IntelliTrace to "debug backwards" to see parameters, threads, and variables at the time of the exception. See this MSDN article for details. (Full disclosure: I work on a team closely related to IntelliTrace).
Mike Stall has given a great and simple solution to your problem:
Mark the methods where you rethrow the exception with the attribute
[DebuggerNonUserCode]
The IDE will consider this is not your code and will not break the debugger in such place, and instead will look further in the stack, showing the next rethrow or the initial exception place.
(if the next rethrow is also annoying, mark it as
[DebuggerNonUserCode]
as well, etc...)