我有两个例子。在第一种情况下,调试器捕获未处理的异常:
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()
为什么堆栈跟踪在第二种情况下被切割到包含方法,以及如何防止它?我需要完整的错误报告堆栈跟踪,否则有时无法在没有完整堆栈跟踪的情况下找到问题所在。
最佳答案
您在 Visual Studio 调试器中看到的是 Visual Studio 托管进程捕获的未处理异常(即前两个堆栈帧之后的所有内容都是该 VS“主机管道”的一部分)。如果禁用托管进程(项目属性 -> 启用 Visual Studio 托管进程),您将在两种情况下看到“短”堆栈跟踪(尽管您不会看到 Main
的堆栈帧> 在你的第二种情况下,因为异常被“处理”,不允许传播到 Main
)。这个较短的堆栈跟踪是您在调试器外部运行应用程序时会看到的堆栈跟踪。
堆栈的工作方式与您想象的一样——每个方法调用都会将另一个堆栈帧压入其上,并且在方法结束时,其堆栈帧被“弹出”或从堆栈中移除。您在异常上看到的堆栈跟踪由堆栈帧组成,从引发异常的帧开始,回到最终处理异常的帧,因为堆栈是“展开的”。
关于c# - 异常在 try/catch 上下文中丢失了部分堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24297571/