异常在try/catch上下文中丢失部分堆栈跟踪

本文关键字:失部 堆栈 跟踪 上下文 try catch 异常 | 更新日期: 2023-09-27 18:09:10

我有两个例子。在第一种情况下,调试器捕获未处理的异常:

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

异常有完整的堆栈跟踪:

   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()

第二种情况:

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

在断点处异常有短的堆栈跟踪:

   at ConsoleApplication28.Program.Exec()

为什么在第二种情况下,stacktrace被切断到包含方法,如何防止它?我需要完整的堆栈跟踪bug报告,否则有时不可能找到问题所在,没有完整的堆栈跟踪

异常在try/catch上下文中丢失部分堆栈跟踪

你在Visual Studio调试器中看到的是Visual Studio Hosting Process正在捕获的未处理异常(即前两个堆栈帧之后的所有内容都是VS"主机管道"的一部分)。如果你禁用托管进程(Project Properties->Enable Visual Studio hosting process),你会在两种情况下看到一个"短"堆栈跟踪(尽管在第二种情况下你不会看到Main的堆栈帧,因为异常被"处理"了,不允许传播到Main)。这个较短的堆栈跟踪是在调试器之外运行应用程序时看到的堆栈跟踪。

堆栈的工作方式和你想象的一样——每个方法调用都会把另一个堆栈帧推到它上面,在方法结束时,它的堆栈帧被"弹出",或者从堆栈中删除。您在异常上看到的堆栈跟踪是由从抛出异常的帧到最终处理异常的帧的堆栈帧组成的,因为堆栈被"展开"。

如果需要完整的堆栈跟踪,可以使用:

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

您可能会得到比您需要的更长的跟踪。要获得更短的跟踪,可以使用:

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 + "   ...";