6

I have two examples. In the first case, debugger catches the unhandled exception:

static void Main(string[] args) {
    Exec();
}
static void Exec() {
    throw new Exception();
}

And the exception has full stacktrace:

   at ConsoleApplication28.Program.Exec() 
   at ConsoleApplication28.Program.Main(String[] args) 
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

The second case:

static void Main(string[] args) {
    Exec();
}
static void Exec() {
    try {
        throw new Exception();
    }
    catch (Exception ex) {
    } // Breakpoint
}

At the breakpoint the exception has short stacktrace:

   at ConsoleApplication28.Program.Exec()

Why stacktraces are cut to the containing method in the second case, and how to prevent it? I need full stacktrace for bugreports, otherwise it's not possible sometimes to find there the problem is, without full stacktrace.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Alex Butenko
  • 3,664
  • 3
  • 35
  • 54
  • "I need full stacktrace for bugreports, otherwise it's not possible sometimes to find there the problem is, without full stacktrace." To answer that part of your question, you need to insert a try-catch structure somewhere "above" where exceptions can occur, perhaps right at the top, in your Main() method. In the catch clause you should write the exceptionObject.ToString() to some file or something for later analysis. – RenniePet Jun 19 '14 at 03:20

2 Answers2

3

What you're seeing in the Visual Studio debugger is the unhandled exception that the Visual Studio Hosting Process is trapping (ie everything after the first two stack frames is part of that VS "host plumbing"). If you disable the hosting process (Project Properties->Enable Visual Studio hosting process), you'll see a "short" stack trace in both scenarios (notwithstanding that you won't see the stack frame for Main in your second case because the exception is "handled", not allowed to propagate up to Main). This shorter stack trace is the stack trace you would see if you were running the application outside the debugger.

The stack works as you would imagine - each method call pushes another stack frame onto it, and at the end of the method its stack frame is "popped", or removed from the stack. The stack trace you see on the exception is composed of the stack frames from the frame where the exception was thrown, back to the frame where the exception is ultimately handled, as the stack is "unwound".

lesscode
  • 6,221
  • 30
  • 58
  • You may want to reorganize this answer to more clearly indicate which part of the stack trace is due to the hosting process and which is due to the catch block. You could then emphasize that stack traces are aggregated as the exception traverses stack levels, so the `Main` part is simply not there yet. – John Saunders Jun 19 '14 at 02:21
  • 1
    But why Main() is not in the second stacktrace? I don't get it. I checked the stacktrace at the point of the exception by System.Diagnostics.StackTrace and Main() is in there. – Alex Butenko Jun 19 '14 at 02:56
  • 2
    The exception stack trace is the stack trace up to the point where the exception is caught. That stack trace grows as the exception bubbles up the levels of the call stack. It shows, "what is the stack trace to date", not "what is the call stack back to the beginning of the program". – John Saunders Jun 19 '14 at 03:01
2

If you need the full stack trace you can use:

catch(Exception ex)
{
    var log = ex.ToString() + Environment.NewLine + new System.Diagnostics.StackTrace(true);
}

You'll probably get a much longer trace than you need. To get a shorter trace you can use:

var NL = Environment.NewLine;
var stack = new StackTrace(true).ToString().Split(new[] { NL }, StringSplitOptions.None).Take(5);
var log = ex.ToString() + NL + String.Join(NL, stack) + NL + "   ...";
AlexDev
  • 4,049
  • 31
  • 36