【发布时间】:2016-02-11 14:32:33
【问题描述】:
重新措辞我的问题以使其成为主题:
我们有一个客户端(众多客户端中只有一个)在使用我们的软件时始终出现内存不足异常。我觉得我们已经消除了可能导致这种情况的常见嫌疑人,并且正在寻找可能导致 OOM 的其他事情(不太标准的原因)的想法。具体来说,由于这似乎是针对单个客户的,是否是由硬件、操作系统或 .Net 安装中的问题引起的?
以下是我所知道的导致 OOM 的原因以及为什么我认为我们已将它们作为嫌疑人排除:
1 - 系统内存不足导致 OOM。 为什么不?因为发生这些异常时系统有几个 GB 可用。
2 - 由于过度分配或内存泄漏,进程耗尽内存导致的 OOM。 为什么不?因为在异常发生时进程只使用了大约 100MB 的内存。我们已经监测了几天的内存使用情况(在相关系统上),并没有发现内存使用有任何显着增加。
3 - 其他系统资源(如文件句柄等)耗尽导致的 OOM。 为什么不?异常仅在普通内存分配期间发生,而不是在打开文件或连接到套接字时发生。
4 - 由于尝试分配具有过多内存碎片的大型数组而导致的 OOM。 为什么不?我们分配的内存块相当小(大部分为 640x480x2)。有这么多可用内存,我很难相信它会如此碎片化以至于这样的事情会失败。
所以,为了清楚起见,我不是在问“为什么我的代码没有运行?”我的代码确实在除一台以外的所有机器上运行。我没有要求任何人调试我的代码。我的问题是:“除了我们已经消除的那些之外,还有哪些其他可能的原因会导致内存不足异常?”或者,“我是否遗漏了一些可能导致我过早消除已知原因之一的东西?”
【问题讨论】:
-
解析损坏的资源会抛出 OOM,例如Image.FromFile() 会在 “文件没有有效的图像格式。”时抛出 OutOfMemoryException。
-
关于 3) 恕我直言,在这种情况下你不会得到 OOM 异常,但你会得到 NULL 句柄等。我想说在这种情况下更有可能得到 NullReferenceExceptions。关于4)实际上这是一个可能的选择。您似乎有 600kB 块,这将是一个大型对象堆 (LOH) fragmentation,因为 LOH 在 GC 后没有被压缩。
-
恕我直言,只有一个选项:由于pinned objects 而导致的 SOH(小对象堆)碎片无法被垃圾回收。
-
测量时,测量虚拟内存和/或私有字节。保留和提交的内存都会导致 OOM。 Never measure working set size,这是最无用的指标之一。我不知道为什么这是任务管理器中的默认列。请改用SysInternals Process Explorer。
-
Take a crash dump 具有正确的位数和完整的内存。使用调试器track down .NET out of memory exceptions。