2

我们对在特定机器上遭受 OutOfMemoryExceptions 的 NUnit 测试进行了测试。

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

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

  1. 出现故障的机器是一个带有 Windows7 x64(6 GB 内存)的 Hyper-V VM
  2. 工作机是物理机 Windows XP(2 GB 内存)

我知道最好的解决方案是清理代码以处理任何 Bitmap 对象,但我很想知道为什么这 2 台机器在执行相同的代码时行为会有所不同?

4

2 回答 2

1

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

您将找到一个表格,其中列出了不同版本的 Windows 之间在 GDI 堆方面的差异。简短的回答:XP = 3Mb 限制,Win7R2x64 = 20Mb 限制。可用 RAM 无关紧要,这些都是硬性限制。

于 2013-09-30T13:40:08.807 回答
1

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

GC 通常不会完成工作,Bitmap 类是一个非常小的对象,不足以自行触发 GC。您必须分配大约 60,000 个才能触发 GC。您永远不会到达那里,除非位图非常小,否则您将首先用完 VM 空间,然后处理。调用 Dispose() 是可选的,但这对于位图不再是可选的,因为终结器无法及时完成工作。

RAM 的数量在这方面没有任何作用,.NET 程序总是对其进行轰炸,无法在 VM 地址空间中找到足够大以适应请求大小的漏洞。位图也是一个问题,它们往往需要大洞。只需要一个加载到尴尬基地址的 DLL 就可以将一个不错的大洞一分为二。否则很容易解决的问题,只需将程序的目标平台设置为AnyCPU即可。一个测试程序有一个配置值。在那台Win7机器上工作。但当然,这不是跳过 Dispose() 调用的正当理由。

于 2013-09-30T13:47:10.867 回答