我正在尝试分析托管进程内存转储,如果本机内存泄漏则可疑。为了能够使用windbg(并从那里使用!heap扩展),我为服务器进程激活了用户模式调用堆栈
我看到很多大小为68的块。在那些块(我可以使用!heap -p -a 手动验证的块)中,有许多形式的调用堆栈
!heap -p -a 000000003ca5cfd0
address 000000003ca5cfd0 found in
_HEAP @ 1ea0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
000000003ca5cfa0 0009 0000 [00] 000000003ca5cfd0 00068 - (busy)
7766bbed ntdll! ?? ::FNODOBFM::`string'+0x000000000001913b
7fef7b76a57 msvcr120!malloc+0x000000000000005b
7fef7b76967 msvcr120!operator new+0x000000000000001f
7fe9a5cdaf8 +0x000007fe9a5cdaf8
您是否知道这些分配是什么,因为它们在我的转储文件中占用了数百MB?
修改 lm显示以下区域 7fe9a5cdaf8 (截断)
start end module name
00000000`773b0000 00000000`774cf000 kernel32 (pdb symbols)
00000000`774d0000 00000000`775ca000 user32 (deferred)
00000000`775d0000 00000000`77779000 ntdll (pdb symbols)
00000000`77790000 00000000`77797000 psapi (deferred)
00000000`777a0000 00000000`777a3000 normaliz (deferred)
00000001`3f810000 00000001`3f818000 ManagedService (deferred)
000007fe`dd2d0000 000007fe`de398000 System_Web_ni (deferred)
答案 0 :(得分:2)
我假设没有为您的应用程序创建本机映像(使用NGen)。在这种情况下,模块(DLL)仅包含永远不会执行的IL代码。因此,从本机的角度来看,不会有任何指向模块内部的堆栈。
相反,IL代码将JIT编译到内存中的另一个位置,例如在你的情况下7fe9a5cdaf8。这就是执行实际代码的地方,这是你从原生代那里看到的。
要将JIT编译指令恢复为其.NET方法描述符,请执行以下操作:
0:000> .symfix
0:000> .loadby sos mscorwks ; *** .NET 2
0:000> .loadby sos clr ; *** .NET 4
0:000> !ip2md 7fe9a5cdaf8
然后输出应显示.NET方法名称(此处示例,因为我没有转储):
MethodDesc: 000007ff00033450
Method Name: ManagedService.Program.Main()
Class: 000007ff00162438
MethodTable: 000007ff00033460
mdToken: 0600001f
Module: 000007ff00032e30
IsJitted: yes
CodeAddr: 000007ff00170120