【发布时间】:2009-09-03 06:05:09
【问题描述】:
我已经在 VS2005 中确认了同样的行为,因此将其称为 .NET (1.1) 错误是错误的。
我将在下面留下原来的问题,但我修改后的问题是:如何让 Visual Studio 给我在调用堆栈窗口中捕获并重新抛出的异常的堆栈跟踪 ,而不是只显示从throw 语句开始的调用堆栈?
情况是我决定 在运行时 全局异常处理程序是打开还是关闭 - 如果它关闭,我希望 VS 捕获异常,以便我可以通过调用堆栈单步执行找出问题所在。
以前,全局异常处理程序要么编译到程序中,要么不编译。但是情况发生了变化,现在我们需要在运行时做出决定——看起来我可能需要回到使用宏的方式来做这件事,但没有宏:
if (allow_bubble_up)
{
Foo();
}
else
{
try
{
Foo();
}
catch (Exception e)
{
GlobalExceptionHandler(e);
}
}
但对我来说,这种方法对 DRY 的感觉非常。
显然 .NET 1.1 中存在一个错误,如果您有一个空的 throw 语句来重新引发捕获的异常,则堆栈跟踪将从发生 throw 的位置开始,而不是整个异常被重新抛出 - 至少,我在几个博客上看到它称为错误,但我无法获得更多关于它的信息。
更具体一点,QuickWatch 中$exception 的StackTrace 属性显示了正确的数据,但VS 中的Call Stack 窗口只显示了throw 语句级别的调用堆栈。
在此示例代码中,我只能看到 Main 的 1 级深度堆栈跟踪,尽管我应该看到对 Foo 的几次调用的堆栈跟踪。
static public void Foo(int i)
{
if (i > 4)
{
throw new ArgumentOutOfRangeException();
}
Foo(i + 1);
}
static void Main(string[] args)
{
bool allow_bubble_up = true;
try
{
Foo(0);
}
catch (Exception e)
{
if (allow_bubble_up)
{
// stack trace just shows Main
throw;
// also just shows Main
//throw new Exception("asdf", e);
// STILL just shows Main
//throw e;
}
else
{
System.Console.WriteLine(e);
}
}
}
Fabrice Marguerie's blog 展示了如何解决 .NET 2.0+ 的某种重新抛出的堆栈跟踪,在底部他说查看 Chris Taylor 的博客以了解如何在 .NET 1.1 中执行此操作。我不得不搜索一下find it on archive.org。我认为我正确地实现了它,但我仍然在 main 处得到一个堆栈跟踪——他的解释不是很清楚,我不想弄乱代码库(包装现有集其他方法中的功能)超过必要。
我可以在捕获和重新引发的异常的属性中看到正确的堆栈跟踪,但是 VS 显示的可导航堆栈跟踪是无用的,因为它只跟踪 throw 语句。如果我从不捕获并重新抛出异常,我确实会获得完整且正确的堆栈跟踪。
如何在 VS 中显示正确的堆栈跟踪? 我希望有某种简单的解决方法,但我一直在搜索错误的术语。
不幸的是,它必须是 VS2003+C#。
如果不清楚,这里是截图(您可能需要右键单击并查看图像):
alt text http://img257.imageshack.us/img257/1124/40727627.png
【问题讨论】:
-
我记得这对于 1.1 非常令人沮丧。当时从未寻求过解决方案,但你并不疯狂。我知道你的意思!但并不像我想象的还要使用 1.1 那样令人沮丧!
-
这看起来是正确的,因为 Main 是 Foo 的调用者,它最终抛出了异常。
-
@Mark Rushakoff:我已经强调了调用堆栈窗口点,这是最大的混淆点。
标签: c# visual-studio stack-trace