【问题标题】:Troubleshooting ERROR_NOT_ENOUGH_MEMORYERROR_NOT_ENOUGH_MEMORY 故障排除
【发布时间】:2010-11-30 02:19:21
【问题描述】:

我们的应用程序在一个特定用户的计算机上失败,ERROR_NOT_ENOUGH_MEMORY(“没有足够的存储空间来处理这个命令”)。

这个错误显然是在我们使用的 Delphi VCL 框架的某个深处引发的,所以我不确定哪个 Windows API 函数负责。

内存有问题吗?调用GlobalMemoryStatus会提供以下信息:

  • dwTotalPhys - 1063150000 (~1 GB)
  • dwAvailPhys - 26735000 (~27 MB)
  • dwAvailPage - 1489000000 (~1.4 GB)

当页面文件中有这么多可用空间时,Windows 会让可用物理内存变得如此之低,这对我来说似乎很奇怪,但我对 Windows 的虚拟内存管理了解不足,无法知道这是否正常或不是。是吗?

如果不是内存,那么会达到哪个资源限制?根据我在网上阅读的内容,ERROR_NOT_ENOUGH_MEMORY 可能是应用程序达到多个限制(GDI 对象、USER 对象、句柄等),不一定是内存。是否有 Windows 强制执行的限制的完整列表?有什么方法可以找出正在达到的限制吗?我尝试了谷歌,但我找不到任何系统的概述。

【问题讨论】:

  • GDI 是我的第一个停靠港。虽然奇怪的是它只发生在一个用户的机器上,但这就是我要开始的地方。也可能是正在使用的手柄数量等。祝你好运!

标签: debugging memory-management out-of-memory


【解决方案1】:

比您列出的任何错误更常见的原因是虚拟内存空间碎片。在这种情况下,虽然总可用内存相当合理,但可用空间被碎片化为当前分配的虚拟内存空间的各个位。因此,当单个连续块无法满足内存请求时,尽管总空闲量足够,您可能会出现内存不足错误。

【讨论】:

  • 这应该很容易通过重新启动尝试同样的事情来检查。有人会认为他们会在将其作为问题发布之前尝试过 SO(但发生了更愚蠢的事情......)
  • @T.E.D. :重新启动并不比简单地杀死故障进程并重试更有效。每个进程在首次创建时都有自己的新虚拟内存空间。该问题通常在长时间运行的应用程序中自然出现,或者在快速运行的应用程序中快速出现,其中大块和小块内存的混合分配和释放相当迅速,具有不同的生命周期。它通常表明某些代码块应该维护一个缓冲区列表以重复使用,而不是不断分配和释放内存。
  • 在Delphi中使用FastMM更能防止虚拟内存碎片。
【解决方案2】:

检查所有可能性。

可以使用免费的GDIView 实用程序监控 GDI 问题。它是一个用户无需安装程序即可启动的单个文件。

另外,在相关机器上安装ProcessExplorer

如果您无权访问机器,请让用户对应用程序监控的状态进行屏幕截图。很有可能,这会给你一些提示。

【讨论】:

  • GDIView 提供了关于“GDI 对象”的有趣令人印象深刻的详细信息。
【解决方案3】:

本案的罪魁祸首是CreateCompatibleBitmap。显然,即使您的系统有足够的内存和大量的 GDI 资源,Windows 也可能会对设备相关位图的可用内存实施相当严格的系统范围限制(参见例如this mailing list discussion)。 (这些系统范围的限制显然是因为 Windows 可能会在视频卡的内存中分配设备相关的位图。)

解决方案只是改用与设备无关的位图 (DIB)(尽管这些位图的性能可能不那么好)。 This KB article 描述了如何为设备选择最佳的 DIB 格式。

资源限制的其他候选者(来自其他人的答案和我自己的研究):

  • GDI 资源(来自此答案)- 使用GDIView 轻松检查
  • 虚拟内存碎片(来自这个答案)
  • 桌面堆 - 请参阅 herehere

【讨论】:

    【解决方案4】:

    我的回答可能有点晚了,但是根据我对同一问题的后期经验,做所有的测试,一步一步地创建 DC,释放它,使用 DIBSection 而不是 CompatibleBitmap,使用泄漏GDI/内存工具等

    最后(哈哈)我发现:

    我正在切换这两个呼叫的优先级,然后整个问题就解决了。

    DeleteDC(hdc);       //do it first (always before deleting objects)
    DeleteObject(obj);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-15
      • 2021-09-11
      • 2012-02-18
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多