在.NET应用程序中,您可以从Exception
对象获取堆栈跟踪。我正在寻找堆栈跟踪中的托管到本机转换(和其他方向)。 Visual Studio调试器可以显示这些特殊帧,但在代码中,我看到了其他内容。有些框架没有托管IL偏移(来自GetILOffset()
方法),但有Visual Studio看不到的模块和方法名称。它们来自哪里,我如何解释它们?
以下屏幕截图显示了我的应用程序中此类堆栈跟踪的示例。黄色突出显示的是Visual Studio指示本机方法的方法。元数据标记“+ number”是托管IL代码偏移量。没有,我怀疑这是一种本地方法。
这是Visual Studio在同一地点显示的内容:
答案 0 :(得分:1)
您正在看到堆栈跟踪的两个不同视图,否则无法使它们相同。它是本机代码堆栈帧干扰视图,可靠地行走本机代码帧需要调试信息,需要PDB文件的类型,只有本机调试器有一个镜头。
顶视图由StackTrace对象生成。它完全跳过本机堆栈帧。您突出显示的是C#方法,它们具有extern
属性。分别为[DllImport]
声明(pinvoke)和[MethodImpl(MethodImplOptions.InternalCall)]
(存在于CLR内部且抖动的代码知道)。他们没有IL,所以从GetILOffset()得到0是预期的。然而,这并不意味着0是一个可靠的指示,你必须找回该属性来过滤它们。
调试器的Call Stack窗口故意隐藏这些方法。调试器无法显示任何有意义的内容,无法在“自动和本地”窗口中显示任何内容。您必须启用非托管调试才能看到更多内容。
调试器视图中的[transition]注释是从抖动元数据生成的,这些信息只能通过调试器接口获得,而不能被StackTrace类考虑。从托管堆栈帧之间的链接生成,GC需要可靠地遍历堆栈帧的元数据,而没有冒险进入非托管堆栈帧的风险,并将本机指针值误解为对象引用。否则,从托管代码转换为本机代码意味着什么,返回,成本就是维护这些链接。这很便宜。