为什么堆栈在 Exception.StackTrace 中被截断? [英] Why does stack get truncated in Exception.StackTrace?

查看:25
本文介绍了为什么堆栈在 Exception.StackTrace 中被截断?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么堆栈的高部分(在 Exception.StackTrace 中)被截断?让我们看一个简单的例子:

Why does the high part of the stack (in Exception.StackTrace) gets truncated? Let's see a simple example:

public void ExternalMethod()
{
  InternalMethod();
}

public void InternalMethod()
{
  try
  {
    throw new Exception();
  }
  catch(Exception ex)
  {
    // ex.StackTrace here doesn't contain ExternalMethod()!
  }
}

这似乎是设计使然".但如此奇怪的设计的原因是什么?它只会让调试变得更加复杂,因为在日志消息中我无法理解是谁调用了 InternalMethod() 并且这些信息通常是非常必要的.

It seems like this is "by design". But what are the reasons for such a strange design? It only makes debugging more complex, because in log messages I can't understand who called InternalMethod() and often this information is very necessary.

至于解决方案(对于那些不知道的人),据我所知,有两种通用解决方案:
1)我们可以记录静态Environment.StackTrace属性,它包含整个堆栈(例如,从最高级别(消息队列)开始,到发生异常的最深方法结束).
2) 我们必须在最高级别捕获和记录异常.当我们需要在较低级别捕获异常来做某事时,我们需要进一步重新抛出(在 C# 中使用throw"语句).

As for solutions (for those who don't know), there are 2 general solutions as I understand:
1) We can log static Environment.StackTrace property, which contains the whole stack (for example, starting at the hiest level (message queue) and ending at the deepest method in which exception occurs).
2) We have to catch and log exceptions on highest levels. When we need to catch exceptions on lower levels to do something, we need to rethrow (with "throw" statement in C#) it further up.

但问题在于这种设计的原因.

But the question is about reasons of such design.

推荐答案

好的,现在我明白你的意思了……抱歉,我对内联问题感到困惑.

Ok, now I see what your getting at... Sorry for my confusion on the inlining thing.

捕获的异常中的堆栈"只是从当前执行的 catch 块到抛出异常的位置的增量.从概念上讲,这种行为是正确的,因为 Exception.StackTrack 会告诉您在此 try/catch 块的上下文中异常发生的位置.这允许在虚拟"调用之间转发异常堆栈并仍然保持准确性.完成此操作的一个经典示例是 .Net Remoting 异常.

The 'stack' in a caught exception is only a delta from the currently executing catch block to where the exception was thrown. Conceptually this behavior is correct in that the Exception.StackTrack tells you where the exception occurred within the context of this try/catch block. This allows exception stacks to be forwarded across 'virtual' calls and still maintain accuracy. One classic example of this being done is .Net Remoting exceptions.

因此,如果您想在 catch 块中获得完整的堆栈报告,您可以将当前堆栈添加到异常堆栈中,如下例所示.唯一的问题是这可能更贵.

Thus if you want a complete stack report in the catch block you would add the current stack to the exception's stack as in the example below. The only problem is this can be more expensive.

    private void InternalMethod()
    {
        try
        {
            ThrowSomething();
        }
        catch (Exception ex)
        {
            StackTrace currentStack = new StackTrace(1, true);
            StackTrace exceptionStack = new StackTrace(ex, true);
            string fullStackMessage = exceptionStack.ToString() + currentStack.ToString();
        }
    }

这篇关于为什么堆栈在 Exception.StackTrace 中被截断?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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