2014-01-18 30 views
5

浏览一些论坛上,我跨this answer来到其中回答者是指以下为本地调用堆栈与CLR有关的本地调用堆栈究竟是什么?

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(在这里我们看CLR调用我认为的主要方法)以及如何查看和理解本地机器上的本机调用堆栈以用于教育目的?

回答

10

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

与托管代码使用堆栈相比,非托管代码使用堆栈的方式没有根本区别。唯一的区别是,您需要一个非托管调试器来实际上请参阅堆栈跟踪中的非托管函数。托管调试器只报告堆栈跟踪中的[托管到本地转换]并隐藏非托管功能。

哪个是有生产力的,你通常不感兴趣的非托管代码,可能会错过所需的PDB,使跟踪准确。其中,对于CLR,需要启用Microsoft Symbol Server。托管堆栈跟踪始终是准确的,因为垃圾收集器和CAS需要执行堆栈遍历才能完成他们的工作,所以CLR提供了硬性保证,堆栈走线可以很好地工作。由于C++代码生成器的优化,非托管堆栈跟踪更加困难,例如,帧指针省略优化对堆栈行走来说非常致命。

你当然可以看到两者。项目+属性,调试选项卡,勾选“启用本地代码调试”选项。

+0

巨大的答案。谢谢。 –

3

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

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