运行测试时特定机器上的OutOfMemoryException

时间:2013-09-30 13:29:18

标签: c# .net out-of-memory gdi handles

我们测试了在特定计算机上遭受OutOfMemoryExceptions的NUnit测试。

经过调查,它似乎不是内存问题,而是Handle问题(我们分配了太多的Bitmap对象而没有释放它们)。

问题是,这在特定机器上运行完美,而在另一台机器上出现此错误则失败。

  1. 故障机器是Windows7 x64(6 GB RAM)的Hyper-V VM
  2. Working Machine是一台物理机Windows XP(2 GB ram)
  3. 我知道最好的解决方案是清理代码以处理任何Bitmap对象,但我有兴趣知道为什么这两台机器在执行相同代码时的行为不同?

2 个答案:

答案 0 :(得分:1)

阅读本文: http://blogs.technet.com/b/markrussinovich/archive/2010/02/24/3315174.aspx

您将找到一个表格,列出了各种版本的Windows与GDI堆之间的差异。简答:XP = 3Mb限制,Win7R2x64 = 20Mb限制。免费RAM并不重要,这些都是硬限制。

答案 1 :(得分:1)

这不太可能,Windows允许你泄漏10,000个句柄,然后它会对你的程序行为方式感到不安,并拒绝让你分配更多。到那时,你已经为位图中的像素数据消耗了大量的虚拟内存空间。存储在非托管内存中的垃圾收集器并不知道它。除非您调用Dispose()或垃圾收集器通过运行终结器来处理它,否则VM空间不会被释放。

GC通常不会完成任务,Bitmap类是一个非常小的对象,不足以自行触发GC。您必须分配大约60,000个来触发GC。你永远不会到达那里,除非位图非常小,否则你将首先耗尽虚拟机空间,接下来处理。调用Dispose()是可选的,但由于终结器无法及时完成工作,因此停止对位图是可选的。

RAM的数量在这方面没有任何作用,.NET程序总是会因为它无法在VM地址空间中找到一个足以满足所请求大小的漏洞而受到轰炸。也是位图的一个问题,它们往往需要大洞。它只需要一个DLL在一个尴尬的基地址加载,将一个漂亮的大洞切成两个。否则,一个容易解决的问题,只需将程序的目标平台设置为AnyCPU即可。测试程序具有该配置值。在Win7机器上运行。但是,当然,这不是跳过Dispose()调用的正当理由。