【问题标题】:allocate more than 1 GB memory on 32 bit XP在 32 位 XP 上分配超过 1 GB 的内存
【发布时间】:2012-04-04 19:46:35
【问题描述】:

我遇到了一个奇怪的问题,我的进程分配的空间似乎略低于 1 GiB。当我的软件给出bad_alloc 异常时,Windows 任务管理器“内存使用”列显示接近 1 GiB 的值。是的,我检查过传递给内存分配的值是否合理。 (不存在会导致失败的竞争条件/损坏)。是的,我需要所有这些记忆,而且没有办法绕过它。 (它是图像的缓冲区,无法进一步压缩)

我不是想一次性分配整个 1 GiB 内存,有几个分配大约 300 MiB。这会导致问题吗? (我会尝试看看是否进行更小的分配会更好)。是否有一些编译器开关或其他我必须设置的东西才能超过 1 GiB?我看到其他人抱怨 2 GiB 的限制,这对我来说很好.. 我只需要多一点:)。我正在使用带有 SP1 的 VS 2005,我在 32 位 XP 上运行它,它是 C++ 语言。

【问题讨论】:

  • 我能想到的两件事,较小的分配,请让嵌入式系统领域之外的 32 位操作系统尽快消亡。而且由于公司政策,我被困在 32 位 Windows 7 上,可用 4 GB 内存中的 2.8 个,这就是我希望它及时消亡的原因。
  • 我深受 32 位操作系统的限制,这让我深感悲痛。这只是我现在必须忍受的事情。
  • SysInternals 有一些工具可以帮助您检查内存碎片。如果您在应用程序开始时分配 1 GB 会发生什么?
  • 我会检查一下 SysInternals 工具,有什么提示吗?我不会一次性分配 1 GiB。有多个分配,每个分配大约 300 MiB。我接近 1 GiB 没有任何问题。
  • 显而易见的尝试是更小的分配,例如每个 1 MB。如果它们有效,您将遇到碎片问题。就试一试吧。如果它们不起作用,那将是一个有用的事实,可以添加到您的问题中。

标签: c++ windows visual-studio memory memory-management


【解决方案1】:

在 32 位操作系统上,一个进程总共有 4GB 的地址空间

在 Windows 上,其中一半是禁止使用的,因此您的进程有 2GB。

这是 2GB 的连续内存。但它会变得支离破碎。您的可执行文件加载到一个地址,每个 DLL 加载到另一个地址,然后是堆栈和堆分配等等。因此,虽然您的进程可能有足够的可用地址空间,但没有足够大的连续块来满足您的内存请求。因此,进行较小的分配可能会解决它。

如果您的应用程序是使用 LARGEADDRESSAWARE 标志编译的,那么它将被允许使用 Windows 可以腾出的剩余 2GB 空间。 (其价值取决于您的平台和环境。

  • 对于在 64 位操作系统上运行的 32 位代码,您将获得完整的 4 GB 地址空间
  • 对于在没有 /3GB 引导开关的 32 位操作系统上运行的 32 位代码,该标志没有任何意义
  • 对于在带有 /3GB 引导开关的 32 位操作系统上运行的 32 位代码,您将获得 3GB 的地址空间。

真的,如果你的应用程序可以处理它,设置标志总是一个好主意(它基本上是一个功能标志。它告诉 Windows 我们 可以处理更多内存,所以如果 Windows 也可以,它应该继续并为我们提供尽可能大的地址空间),但您可能不能依赖它产生影响。除非您使用的是 64 位操作系统,否则它不太可能为您买太多。 (/3GB 引导开关是必要的,而且已知会导致驱动程序出现问题,尤其是视频驱动程序)

【讨论】:

  • 在 XP 上,您还需要使用 /3GB boot.ini 开关。
  • 我只是不相信我的软件会将内存碎片化这么多,但似乎就是这样 :) 通过创建一个尝试分配更小且更小的异常处理程序,我得到了大约 1.6 GiB小块直到它成功。我尝试使用 LARGEADDRESSAWARE 标志,但没有使用 3GB 开关。我看到提到这会对程序的性能产生影响,这是真的/大吗?
  • @justanothercoder:嗯,很容易造成碎片。在正确的位置分配一个字节,您的 2GB 地址空间已减少到两个 1GB 地址空间。在正确的地方多了两个字节,你就有了四个 512MB 的字节。当然,通常分配是为了尽量减少碎片,但我的观点是很容易将你的内存空间碎片化
  • 我试图以这样的方式进行设计:/ 显然我没有成功。
  • @justanothercoder:如果没有 XP 上的 /3GB 开关,LARGEADDRESSAWARE 将无法完成很多工作 - 有关启用它的信息,请参阅此页面:msdn.microsoft.com/en-us/windows/hardware/gg487508 我从未遇到过使用此配置的任何明显性能问题,尽管启用此模式时某些视频驱动程序曾经出现问题 - 我不知道是否仍然如此。
【解决方案2】:

分配大块连续内存始终是个问题。 很有可能以更小的块获得更多的内存

你应该重新设计你的记忆结构。

【讨论】:

  • 实际上没有必要,我只会提供比要求的缓冲区更小的缓冲区,我的代码似乎并不关心 :) 我创建了一个尝试分配的循环,如果它失败,它尝试分配一个较小的部分。这一直持续到它起作用为止。
【解决方案3】:

您怀疑更大的 300MB 分配是正确的。您的进程将能够接近 2GB(如果您使用 /3GB boot.ini 开关和 LARGEADDRESSAWARE 链接标志,则为 3GB),但不是一个大的连续块。

对此的典型解决方案是将请求分解为固定大小(例如 256x256x4 字节)的小块或条带,并编写一个中间类来隐藏此表示细节。

您可以通过编写一个分配不同大小块的小型分配循环来快速验证这一点。

【讨论】:

    【解决方案4】:

    您也可以查看 MSDN 中的this 功能。 1GB 从这里敲响了警钟:

    此参数必须大于等于 13 页(例如, 53,248 在具有 4K 页面大小的系统上),并且小于系统范围 最大(可用页数减去 512 页)。默认尺寸 是 345 页(例如,在具有 4K 页面大小)。

    这里他们提到一个进程允许的默认最大页数是 345 页,略大于 1GB。

    【讨论】:

    • 略大于 1 MB,而不是 1 GB。
    【解决方案5】:

    当我有一些类似的大分配器要做时,我使用 Windows 函数 VirtualAlloc,以避免对默认分配器造成压力。

    另一种方法可能是在您的项目中使用nedmalloc

    【讨论】:

      猜你喜欢
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      • 2010-11-09
      • 2013-01-24
      • 2013-11-27
      • 1970-01-01
      • 2014-10-14
      相关资源
      最近更新 更多