究竟什么是CLR的本机调用堆栈?

时间:2014-01-18 12:48:51

标签: c# clr

浏览一些我遇到this answer的论坛,其中回答者将以下内容称为本机调用堆栈

00000000`0014ea10 00000642`7f67d4a2 0x642`80150142
00000000`0014ea90 00000642`7f5108f5 mscorwks!CallDescrWorker+0x82 
00000000`0014eae0 00000642`7f522ff6 mscorwks!CallDescrWorkerWithHandler+0xe5
00000000`0014eb80 00000642`7f49a94b mscorwks!MethodDesc::CallDescr+0x306 
00000000`0014edb0 00000642`7f474ae4 mscorwks!ClassLoader::RunMain+0x23f
00000000`0014f010 00000642`7f5efb1a mscorwks!Assembly::ExecuteMainMethod+0xbc 
00000000`0014f300 00000642`7f467d97 mscorwks!SystemDomain::ExecuteMainMethod+0x492
00000000`0014f8d0 00000642`7f482c24 mscorwks!ExecuteEXE+0x47

关于CLR的本机调用堆栈究竟是什么(这里我们正在考虑调用我认为的Main方法的CLR)以及如何在本地计算机上查看和理解所述本机调用堆栈以用于教育目的?

2 个答案:

答案 0 :(得分:10)

是的,这些是用C ++编写的非托管函数。用于编写CLR的语言。

与托管代码使用堆栈的方式相比,非托管代码使用堆栈的方式没有根本区别。唯一的区别是您需要一个非托管调试器来实际查看堆栈跟踪中的非托管函数。托管调试器只报告堆栈跟踪中的[Managed to Native Transition]并隐藏非托管函数。

哪种方法很有效率,您通常不会对非托管代码感兴趣,并且很可能缺少必要的PDB来使跟踪准确。对于CLR,需要启用Microsoft Symbol Server。托管堆栈跟踪总是准确的,CLR可以保证堆栈遍历可以正常工作,因为垃圾收集器和CAS需要执行堆栈遍历才能完成工作。由于C ++代码生成器的优化,非托管堆栈跟踪更加困难,例如,帧指针省略优化对于堆栈遍历非常致命。

你当然可以看到两者。 Project + Properties,Debug选项卡,勾选“启用本机代码调试”选项。

答案 1 :(得分:3)

“本机调用堆栈”是指通过非托管库调用的(部分)调用堆栈。由于操作系统不受管理,因此您总是有一些托管堆栈的非托管入口点。但是,您也可以在其上部使用非托管方法,即,如果托管代码调用系统函数。调用堆栈可以包含任意数量的托管到本机和本机到托管的转换。要查看合理的内容,应该打开“非托管调试”。

在上面的示例中,您会看到源自mscorwks.dll的调用,这是包含.NET执行引擎的主dll。由于缺少该库的符号(除非您已下载它们 - 请参阅“Microsoft符号服务器”上的google),您只能查看不同功能的入口点。一行mscorwks!CallDescrWorkerWithHandler+0xe5表示调用源自mscorwks.dll中名为“CallDescrWorkerWithHandler”的函数,该函数从该函数开始的0xe5字节。