I never thought about it, but it turns out that exception’s stack trace does not contain the full stack. Instead, it contains only frames between the point where the exception was thrown and the point it is caught. This is bad if exception is caught close to the point of throwing and logged:
using System;
namespace ExceptionTrace
{
class Program
{
void f1()
{
f2();
f3();
}
void f2() { f4(); }
void f3() { f4(); }
void f4()
{
try { throw new Exception("Boo!"); }
catch (Exception ex)
{
Console.WriteLine("Problem: " + ex); // stack trace contains only f4()
}
}
static void Main(string[] args)
{
new Program().f1();
}
}
}
This prints:
Problem: System.Exception: Boo! at ExceptionTrace.Program.f4() in C:\Ivan\dev\exp\ExceptionTrace\Program.cs:line 18 Problem: System.Exception: Boo! at ExceptionTrace.Program.f4() in C:\Ivan\dev\exp\ExceptionTrace\Program.cs:line 18
Note that both stack traces are exactly identical and contain only one frame. The message does not say whether f4() was called from f2() or from f3(). This information can be obtained by calling new StackTrace()
inside the catch
, which returns the full stack, but this stack trace is not part of the exception.
If we rethrow the exception and let it travel up the call chain, its StackTrace
will automatically grow to reflect additional frames, but it will never include the frames above the catching block.