5

我们的应用程序在一个特定用户的计算机上失败了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 强制执行的限制的完整列表?有什么方法可以找出正在达到的限制吗?我尝试了谷歌,但我找不到任何系统的概述。

4

4 回答 4

4

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

于 2009-09-21T14:23:58.973 回答
4

检查所有可能性。

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

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

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

于 2009-09-21T19:24:16.117 回答
3

在这种情况下,罪魁祸首是CreateCompatibleBitmap。显然,即使您的系统有足够的内存和大量的 GDI 资源,Windows 也可能会在系统范围内对设备相关位图可用的内存实施相当严格的限制(例如,请参阅此邮件列表讨论)。(这些系统范围的限制显然是因为 Windows 可能会在视频卡的内存中分配与设备相关的位图。)

解决方案是简单地使用与设备无关的位图 (DIB)(尽管这些位图可能无法提供相当好的性能)。 这篇知识库文章介绍了如何为设备选择最佳的 DIB 格式。

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

于 2010-05-10T14:02:41.150 回答
0

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

最后(大声笑)我发现:

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

DeleteDC(hdc);       //do it first (always before deleting objects)
DeleteObject(obj);
于 2013-03-08T01:10:43.950 回答