【问题标题】:Where are managed/native transitions in the StackTrace?StackTrace 中的托管/本机转换在哪里?
【发布时间】:2015-03-26 02:06:51
【问题描述】:

在 .NET 应用程序中,您可以从 Exception 对象中获取堆栈跟踪。我正在该堆栈跟踪中寻找托管到本机的转换(和其他方向)。 Visual Studio 调试器可以显示这些特殊帧,但在代码中,我看到了其他内容。有些帧没有托管 IL 偏移量(来自 GetILOffset() 方法),但具有 Visual Studio 看不到的模块和方法名称。它们来自哪里,我该如何解释它们?

以下屏幕截图显示了我的应用程序中此类堆栈跟踪的示例。黄色突出显示的是 Visual Studio 指示本机方法的方法。元数据标记“+number”是托管 IL 代码偏移量。哪里没有,我怀疑是原生方法。

这是 Visual Studio 为同一地点显示的内容:

【问题讨论】:

    标签: .net stack-trace


    【解决方案1】:

    您会看到堆栈跟踪的两个不同视图,否则无法使它们相同。干扰视图的是本机代码堆栈帧,可靠地遍历本机代码帧需要调试信息,需要 PDB 文件的那种,只有本机调试器才有机会。

    顶视图由 StackTrace 对象生成。它完全跳过本机堆栈帧。您突出显示的实际上是 C# 方法,它们具有 extern 属性。分别用于[DllImport] 声明(pinvoke)和[MethodImpl(MethodImplOptions.InternalCall)](存在于CLR 中并且抖动知道的代码)。它们没有 IL,因此预期从 GetILOffset() 获得 0。然而,这并不意味着 0 是一个可靠的指示,您必须找到属性来过滤它们。

    调试器的调用堆栈窗口有意隐藏了这些方法。调试器无法显示对它们有意义的任何内容,在 Autos 和 Locals 窗口中没有显示任何内容。您必须启用非托管调试才能查看更多信息。

    调试器视图中的 [transition] 注释是从抖动元数据生成的,这些信息只能通过调试器接口获得,StackTrace 类不考虑这些信息。从托管堆栈帧之间的链接生成元数据,GC 需要可靠地遍历堆栈帧,而不会有误入非托管堆栈帧和将本机指针值错误解释为对象引用的风险。这就是从托管代码过渡到本机代码并返回的意思,成本是维护这些链接。很便宜。

    【讨论】:

    • DispatchMessage 方法是[DllImport] extern。有趣的是,它在堆栈跟踪中连续出现了两次。外部方法可以以托管方式调用自身吗?还是堆栈跟踪错误?对于我的诊断案例,知道框架中的方法是否是外部的可能已经足够了。 stackoverflow.com/q/19768407/143684 应该可以帮助我,尽管我希望有一个简单的 IsExtern 属性...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多