我有两个例子。在第一种情况下,调试器捕获未处理的异常:
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()
为什么在第二种情况下,stacktraces被切割为包含方法,以及如何防止它?我需要对bug报告进行完整的堆栈跟踪,否则有时候找不到问题是没有完全堆栈跟踪的。
答案 0 :(得分:3)
您在Visual Studio调试器中看到的是Visual Studio托管进程正在捕获的未处理异常(即前两个堆栈帧之后的所有内容都是VS"主机管道的一部分" )。如果您禁用托管过程(项目属性 - >启用Visual Studio托管过程),您将看到"短"两种情况下的堆栈跟踪(尽管在第二种情况下你没有看到Main
的堆栈帧,因为异常是"处理",不允许传播到{{1 }})。这个较短的堆栈跟踪是您在调试器外部运行应用程序时将看到的堆栈跟踪。
堆栈的工作方式与您想象的一样 - 每个方法调用将另一个堆栈帧推送到其上,并且在方法结束时,其堆栈帧被弹出"或从堆栈中移除。您在异常上看到的堆栈跟踪由抛出异常的帧中的堆栈帧组成,返回到最终处理异常的帧,因为堆栈是" unwound"。
答案 1 :(得分:1)
如果需要完整的堆栈跟踪,可以使用:
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 + " ...";