2011-09-28 64 views
0

运行在32位计算机上的32位.net应用程序遇到OutOfMemoryException。然后我进行了一次完整的内存转储,尽管使用WinDbg我可以验证是否有很多内存正在使用,但我想知道为什么我们会得到OOME,但根据WinDbg的输出“!eeheap -gc”,GC堆大小是只有1GB左右,所以看起来1.5GB的.net存在相当大的空间。OutOfMemoryException,转储文件大小和GC堆大小

这里的是输出的部分:

0:000> !eeheap -gc 
Number of GC Heaps: 1 
generation 0 starts at 0x6a12ffcc 
generation 1 starts at 0x6a12ffc0 
generation 2 starts at 0x016a1000 
ephemeral segment allocation context: (0x6a12ffd8, 0x6a12ffe4) 
segment begin allocated  size 
016a0000 016a1000 0269ff64 0x00ffef64(16772964) 
... 

69130000 69131000 6a12ffd8 0x00ffefd8(16773080) 
Large object heap starts at 0x026a1000 
segment begin allocated  size 
026a0000 026a1000 03698a98 0x00ff7a98(16743064) 
... 

70020000 70021000 70a7d750 0x00a5c750(10864464) 
Total Size 0x3c67abb4(1013427124) 
------------------------------ 
GC Heap Size 0x3c67abb4(1013427124) 

这是可以预料?剩余的〜500MBs在哪里?

更多的细节:

  • 转储文件本身的大小2.007.000.476字节。
  • 运行该软件的计算机只有1GB的物理RAM,但该计算机的虚拟内存设置为增长到3GB(因此该应用程序应该可以增长到最大为1.5GB的32位。网络应用程序)。

回答

1

最有可能的过程不知道3GB。这是每个过程设置。

此外,如果你想看到总的内存使用情况,你可以使用!堆-s。这会给你一个每个堆所做的事情和它使用的内存量的总结。这也会向你显示碎片问题。将它与托管堆结合起来,它应该给你一个总内存使用的想法。

+0

如果我没有弄错,这个过程应该能够达到1.5G。我的问题不是我想改变极限(如3GB)。顺便说一句。从其他答案/评论,所以我觉得这是不可能的。我想知道如果不在.net堆中,其他500个左右的位置。我尝试过!堆,但只有总计大约100MB(当我有更多时间时必须再次检查,该命令的输出需要一些适应) –

+0

您需要检查储备大小。这基本上告诉你该进程请求了多少进程地址空间。这很高是什么会导致OOM错误。那么这很简单,但这是一个好的开始,并且将覆盖90%的案例。 – Zipper

0

近2 Gb的转储大小表示进程的用户地址空间已满。内存不仅被.Net内存分配填充,还被填充为本地(C/C++)分配,jitted代码,二进制文件,堆栈,... 使用Windbg,使用!address -summary检查虚拟空间的使用情况。 要获得全局视图,还可以使用DebugDiag分析转储。

+0

!address -summary告诉我,RegionUsageIsVAD使用1.917.264 KB /〜98%Pct(Busy)。不知道这对我有什么帮助。 –

+0

VAD是通过VirtualAlloc未被识别为win32堆分配的内存。一般来说.Net内存和来自Win32堆的大对象被标记为VAD – plodoc

+0

你看过!eeheap的输出(没有-gc)来检查加载器使用的内存吗? – plodoc