【问题标题】:OUT OF MEMORY only when virtual limit is hit?只有在达到虚拟限制时才会出现内存不足?
【发布时间】:2009-10-05 12:29:01
【问题描述】:

据我所知,在 win32 中,每个程序都会收到 4GB 的虚拟内存。内存管理器负责将内存块从物理内存卸载到磁盘。

这是否意味着 malloc 或任何其他内存分配 API 仅在达到虚拟限制时才会抛出 OUT_OF_MEMORY 异常?我的意思是即使程序远离其虚拟大小限制,malloc 也有可能失败,例如没有物理内存可以卸载到磁盘。假设磁盘有无限容量并且没有设置具体限制。

【问题讨论】:

  • "...现在应该清楚为什么“内存不足”错误通常与您拥有多少物理内存或可用存储量无关。几乎总是关于地址空间,在 32 位 Windows 上相对较小且容易碎片化......”所以碎片化了。
  • 次要点:malloc() 失败将返回 NULL 而不是抛出异常。 new 抛出异常。至少这是它需要做的事情,操作系统可能会做其他事情,并且确实可能​​会根据失败的原因做不同的事情。

标签: c++ c memory-management winapi


【解决方案1】:

是的,这是可能的。请记住,内存可能是碎片化的,malloc 将无法找到足够大的块来满足您请求的大小。这很容易在您达到 4 GiB 限制之前完成。

【讨论】:

  • 您好,内存碎片引发 OOM?对于不太常见的情况,这是一个有点严重的错误......
  • 当分配器找不到足够的(连续的)内存时,它还应该怎么做?
【解决方案2】:

Win 32 的虚拟内存限制为 2Gb。在 Win 64 上,它要大得多。

malloc 不会抛出异常 - 它返回 NULL。 NULL 返回或异常,内存管理器可能会在达到 2Gb 限制之前失败

  • 页面文件不够大。如果页面文件受到策略的限制,或者缺乏扩展空间:如果页面文件的可用性无法满足内存分配,那么它们将失败。

  • 碎片。底层内存管理器以 4Kb 块分配内存。很有可能,通过分配和解除分配模式,最终会分配少量内存,但虚拟内存碎片化意味着没有足够大的连续区域来满足特定请求。

【讨论】:

  • 使用微软的补丁可以将 Win32 内存限制扩展到 3.5 GB
  • Window 的地址空间可以通过编译和启动时间标志扩展到 3Gb/进程。对于将 PCI 总线映射到 CPU 的 4Gb 地址范围(没有 PAE)的 PC,3.5Gb 是典型的可用内存限制
  • 使用 /3Gb 开关是一个非常糟糕的主意,我认为它不值得一提。但值得一提的是,在 Windows 64 上,可以为 32 位应用程序提供完整的 4Gb 地址空间(只要它与 /largeaddressaware 标志链接)。
【解决方案3】:

有关 Windows 虚拟内存的完整章节,请查看 Mark Russinovich 博客上的这篇文章(这里还有很多其他很棒的东西):

Pushing the Limits of Windows: Virtual Memory

如果内存碎片是您的问题并且编写自定义分配器不是您的事,您可以考虑启用低碎片堆:

Low Fragmentation Heap (Windows)

请注意,这几天默认开启。

【讨论】:

    【解决方案4】:

    如果没有大的区域,如何分配一些较小的区域?

    【讨论】:

    • 这样做有什么好处?如果程序要求一个大的连续内存块,它可能打算将它用作一个大的连续内存块,并且几个较小的块需要内置额外的计算才能像这样使用。无论如何,内存不足的程序很可能很快就会用完,因此可能会浪费额外的内存回收措施。
    • 它有什么好处?有可能使算法适应几个较小的内存块。所以它可能会导致一个工作程序。对我来说似乎很公平。
    猜你喜欢
    • 2013-09-01
    • 2016-01-12
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    相关资源
    最近更新 更多