为什么!DumpHeap -stat中的对象总和不匹配!EEHeap -gc?

时间:2015-10-27 18:09:48

标签: c# .net windbg

我在WinDbg中查看完整的应用程序转储,并试图了解我的内存消耗的位置。

我已经解析了!DumpHeap -stat的输出并总结了此报告中的总内存,得到了~7 GB。相比之下,如果我运行!EEHeap -gc,它会报告总共~11 GB。

为什么两份报告之间有这么大的差异?如何找出额外4 GB的位置?

2 个答案:

答案 0 :(得分:3)

!eeheap的值是.NET分配的段大小的总和。

此值始终大于!dumpheap的输出总和。在某些情况下,它有很大不同,因为某些段中只有少数对象,例如固定对象,用于本机PInvoke或COM互操作的东西。这可以防止.NET发布段。您可以使用!gchandles检查固定对象。

根据!eeheap报告的< unknown> 值交叉检查!address -summary的值。假设您没有直接调用VitualAlloc()且不使用MSXML的本机代码,!eeheap的值应接近该值。

答案 1 :(得分:1)

我是.Net团队的开发者。我相信这可能是SOS中的一个错误。 对于eeheap,我们计算段大小的方式是使用段中最后一个对象的结束地址减去段的起始地址。然后将所有这些段大小一起添加以获得总堆大小。

以下是sos eeheap(https://github.com/dotnet/coreclr/blob/bc146608854d1db9cdbcc0b08029a87754e12b49/src/ToolBox/SOS/Strike/eeheap.cpp)的代码,您可以查看GCPrintSegmentInfo,GCPrintLargeHeapSegmentInfo和GCHeapInfo。

有时,由于对象在片段中对齐,片段大小实际上不会等于同一片段中的总对象大小。还有!DumpHeap过滤掉一些不活的对象。这两个因素可能会导致列出的对象的总大小!DumpHeap不等于!eeheap。但4GB似乎比平常更大。它可能是错误。但是如果没有我可以玩的东西,我无法得出结论。

你可以使用connect向我们提交一个bug,我们来看看。这是内疚https://connect.microsoft.com/IE/content/content.aspx?ContentID=29582。 出于调查目的,如果您不介意,可以向我们发送一个可以重现您的问题的程序或转储吗?这对我们的调查很有帮助。 感谢