preserving原堆栈跟踪/ .NET中的异常LineNumbers [英] Preserving original StackTrace/LineNumbers in .NET Exceptions

查看:156
本文介绍了preserving原堆栈跟踪/ .NET中的异常LineNumbers的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

理解的区别的抛出前抛出,为什么原来的堆栈跟踪preserved在这个例子:

Understanding the difference between throw ex and throw, why is the original StackTrace preserved in this example:

    static void Main(string[] args)
    {
        try
        {
            LongFaultyMethod();
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }

    static void LongFaultyMethod()
    {
        try
        {
            int x = 20;
            SomethingThatThrowsException(x);
        }
        catch (Exception)
        {
            throw;
        }
    }

    static void SomethingThatThrowsException(int x)
    {
        int y = x / (x - x);
    }

但不是在这一个:

But not in this one:

    static void Main(string[] args)
    {
        try
        {
            LongFaultyMethod();
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }

    static void LongFaultyMethod()
    {
        try
        {
            int x = 20;
            int y = x / (x - 20);
        }
        catch (Exception)
        {
            throw;
        }
    }

第二种情况是生产作为相同的输出抛出前会?

在这两种情况下,人们期望看到其中y初始化的行号。

In both cases, one expects to see the line number where y is initialized.

推荐答案

我不知道这种限制是否是C#语言中,CLI或微软执行这些内,但你的第二个例子是这样的情况,其中一个需要显式调用 Exception.Internal preserveStackTrace 作为记录在下面的帖子。由于这种方法是内部,它一般要通过反射调用。参与这个性能问题可以通过创建几乎完全缓解的动作<异常> 的调用,如在这个答案的末尾

I'm not sure whether this limitation is within the C# language, the CLI, or the Microsoft implementation of these, but your second example is a case where an explicit call to Exception.InternalPreserveStackTrace is required as documented in the following post. Since this method is internal, it generally has to be called through reflection. The performance issues involved in this can be almost completely alleviated by creating an Action<Exception> for the call, as shown at the end of this answer.

参考:<一href="http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-$p$pserving-the-full-call-stack-trace.aspx">Rethrowing异常和preserving充分调用堆栈跟踪

编辑:重新审视ECMA-335分区我§12.4.2(异常处理)和分区III§4.24(重新抛出)之后,我现在相信你所看到的行为是一种语义错误在CLR(Microsoft实现的CLI)。唯一特别提及行为是A 重新抛出不改变对象中的堆栈跟踪。在这里所描述的情况下,重新抛出其实是在改变堆栈跟踪,使得 preserveStackTrace 破解一个解决方法一个知道CLR的缺陷。

After reexamining ECMA-335 Partition I §12.4.2 (Exception handling) and Partition III §4.24 (rethrow), I now believe that the behavior you are seeing is a semantic error in the CLR (Microsoft's implementation of the CLI). The only specific reference to the behavior is "A rethrow does not change the stack trace in the object." In the case described here, the rethrow is in fact altering the stack trace, making the PreserveStackTrace hack a workaround for a know CLR flaw.

static void LongFaultyMethod() 
{ 
    try 
    { 
        int x = 20; 
        int y = x / (x - 20); 
    } 
    catch (Exception ex) 
    { 
        PreserveStackTrace(ex); // <-- add this line
        throw; 
    } 
} 

preserveStackTrace 这里是从博客条目之一的优化:

PreserveStackTrace here is an optimization of the one from that blog entry:

private static readonly Action<Exception> _internalPreserveStackTrace =
    (Action<Exception>)Delegate.CreateDelegate(
        typeof(Action<Exception>),
        typeof(Exception).GetMethod(
            "InternalPreserveStackTrace",
            BindingFlags.Instance | BindingFlags.NonPublic));

public static void PreserveStackTrace(Exception e)
{
    _internalPreserveStackTrace(e);
}

这篇关于preserving原堆栈跟踪/ .NET中的异常LineNumbers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆