代码之家  ›  专栏  ›  技术社区  ›  Mark Rushakoff

显示重新抛出的异常的堆栈跟踪,而不是从抛出点的堆栈跟踪

  •  3
  • Mark Rushakoff  · 技术社区  · 16 年前

    我把原来的问题留在下面,但我修改的问题是:如何让VisualStudio给我捕获并重新抛出的异常的堆栈跟踪 在调用堆栈窗口中 ,而不是仅从 throw 陈述

    情况是我正在决定 运行时

    以前,全局异常处理程序要么编译到程序中,要么不编译。但是情况已经改变了,现在我们需要在运行时做出决定——看起来我可能需要回到宏的方式,但是没有宏:

    if (allow_bubble_up)
    {
        Foo();
    }
    else
    {
        try
        {
            Foo();
        }
        catch (Exception e)
        {
           GlobalExceptionHandler(e);
        }
    }
    

    极其 反对干,对我来说。


    显然,在.NET1.1中有一个bug,如果你有一个空的 发生,而不是重新抛出整个异常的堆栈跟踪——至少,我在一些博客上看到它被称为bug,但我无法获得更多关于它的信息。

    更具体地说 StackTrace 性质 $exception

    在这个示例代码中,我只能看到 Main 应该 查看对的几个调用的堆栈跟踪 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 展示了如何在.NET2.0+中绕过某种重新抛出的堆栈跟踪,在底部,他说要查看Chris Taylor的博客,了解如何在.NET1.1中实现。我必须找一点时间 find it on archive.org 认为

    我可以在捕获并重新引发的异常的属性中看到正确的堆栈跟踪,但是VS显示的可导航堆栈跟踪是无用的,因为它只跟踪 陈述如果我从未捕获并重新抛出异常,我

    如何在VS中显示正确的堆栈跟踪? 我希望有一些简单的解决方法,我只是在寻找错误的术语。

    不幸的是,这必须是VS2003+C。

    如果不清楚,这里有一个屏幕截图(您可能需要右键单击并查看图像):

    alt text http://img257.imageshack.us/img257/1124/40727627.png

    5 回复  |  直到 16 年前
        1
  •  4
  •   Jason Williams    16 年前

    VisualStudio将显示它所在位置的调用堆栈 .

    在一个 异常,它将在引发该异常的位置停止。i、 e.你的“抛出”声明。但是,如果您的代码处理异常,那么VisualStudio会假定您知道自己在做什么,并忽略异常。它只会在将异常重新抛出Main()时捕获异常,因为您没有在程序中处理它。

    如果要在visual studio中捕获原始异常,有两个选项:

    • 未处理 例外情况。这当然意味着您的程序在运行时不会处理异常,因此这不是一种非常有用的方法!

    • 使用您的代码捕获并重新抛出异常(正如您正在做的),但请将Visual Studio配置为在首次抛出内部异常时停止。转到调试>异常并勾选“公共语言运行时”异常框(针对任何异常停止)或浏览子树以针对特定异常启用异常捕获(提示:如果您知道异常名称,请点击查找…按钮并输入部分名称,例如“FileNotFound”,以快速查找异常)。这将使VS在内部异常处停止,并且只有在检查异常详细信息后选择继续执行时,才转到catch{}语句。

        2
  •  3
  •   Shiraz Bhaiji    16 年前

    您可以抛出一个新异常,将异常e作为内部异常放置。然后读取内部异常的堆栈跟踪。

        3
  •  3
  •   Mark Rushakoff    16 年前

    事实证明,如果你知道正确的搜索词,那么 我试图解决的问题的答案。在MSIL中,它被称为 异常过滤 it is available in VS2003 .

    在Visual Basic.NET中,有一个名为“catch when”的构造,它仅在给定谓词通过时执行catch。 This MSDN blog 有一个很好的例子说明了catch when在VB.NET中是如何工作的,与C#的catch投掷结果(如我的)相比。

    Exception Filter Inject 这可用于“为没有异常过滤器支持的语言(如C#)提供异常过滤器支持”——关键是它在现有程序集上运行,因此如果您最终使用它,它确实会在构建过程中引入一个尴尬的阶段。


    受通缉的 要做到这一点,不知何故让我找到了异常过滤,就是能够在运行时设置要捕获的异常的类型——如果假设异常冒泡,我会尝试捕获一个永远不会被调用的子类异常,否则我只会捕获一个基本异常。我真的不确定这在.NET1.1中是否可行,因为这基本上需要一个泛型——但在反射中可能是可行的,我只是在我的研究中从来没有走那么远。

        4
  •  1
  •   sgmoore    16 年前

    除了启用“第一次异常时中断”之外,我不知道这将如何工作,也不知道VS2003或VS2005中会有什么帮助。(可能是VS2010中新的调试/重播功能)

        5
  •  1
  •   user7116    16 年前

    您所描述的是调用堆栈窗口的预期行为。当VisualStudio在 throw 线

    归结起来,VisualStudio的调用堆栈窗口不知道异常中包含的堆栈跟踪。