0

我有以下问题:

在 Windows 机器上运行的程序(32 位,3.1Gb 内存,VC++2008 和 mingw 编译代码)失败并bad_alloc抛出异常(在分配大约 1.2Gb 后;尝试分配 900 万双精度向量时抛出异常,即大约 75Mb)还有大量可用的 RAM(至少根据任务管理器)。

在 Linux 机器(32 位、4Gb 内存;32 位、2Gb 内存)上运行的相同程序运行良好,峰值内存使用量约为 1.6Gb。有趣的是,由 mingw 生成的 win32 代码在 wine 下的 4Gb linux 机器上运行也因 bad_alloc 而失败,尽管在 Windows 下运行时在不同的(稍后)位置...

可能的问题是什么?

  • 堆碎片?(我怎么知道?这怎么解决?)
  • 堆腐败?(我已经在启用 pageheap.exe 的情况下运行了代码,没有报告任何错误;实现了带边界检查的向量访问 --- 再次没有错误;代码基本上没有指针,只使用了std::vectors 和std::lists。在 Valgrind 下运行程序( memcheck) 消耗过多内存并提前结束,但没有发现任何错误)
  • 记不清???(应该有足够的内存)

此外,在 linux 版本运行时(甚至在内存较少的机器上),windows 版本失败的原因可能是什么?(另请注意,/LARGEADDRESSAWARE 链接器标志与 VC+2008 一起使用,如果这可以产生任何影响)

任何想法都将不胜感激,我对此束手无策...... :-(

4

4 回答 4

5

它与系统中有多少 RAM 无关。您的虚拟地址空间不足。对于 32 位 Windows 操作系统进程,用户模式的 2GB(LARGEADDRESSAWARE 的情况下为 3GB)和内核的 2GB 中获得 4GB 的虚拟地址空间(无论您使用多少 RAM)。当您尝试使用 new 分配内存时,操作系统将尝试找到足够大以满足内存分配请求的虚拟内存的连续块。如果您的虚拟地址空间严重碎片化,或者您正在请求一个巨大的内存块,那么它将无法抛出 bad_alloc 异常。检查您的进程正在使用多少虚拟内存。

于 2009-10-24T12:39:00.987 回答
2

在 Windows XP x86 和默认设置下,1.2 GB 大约是在系统库、代码、堆栈和其他东西获得它们的份额之后,您为堆留下的所有地址空间。请注意,largeaddressaware 要求您使用 /3GB 引导标志进行引导,以尝试为您的进程提供高达 3GB 的空间。/3GB 标志会导致许多 XP 系统不稳定,这就是默认情况下不启用它的原因。

Windows x86 的服务器变体通过使用 3GB/1GB 拆分和使用 PAE 允许使用全部 4GB RAM,为您提供更多地址空间。

Linux x86 默认使用 3GB/1GB 拆分。

即使是 32 位进程,64 位操作系统也会为您提供更多地址空间。

于 2009-10-24T14:10:08.363 回答
0

详细说明虚拟内存:您的应用程序在尝试分配单个 90MB 数组时失败,并且没有可以容纳的连续虚拟内存空间。如果您切换到使用较少内存的数据结构,您可能会走得更远——也许是某个类通过使用所有数据都保存在 1MB(左右)叶节点中的树来近似一个巨大的数组。此外,在 C++ 下,当进行大量分配时,如果所有这些大分配的大小相同,这真的很有帮助,这有助于重用内存并保持碎片更少。

但是,从长远来看,正确的做法是简单地切换到 64 位系统。

于 2009-10-24T22:06:09.233 回答
0

你是在Debug模式下编译吗?如果是这样,分配将生成大量调试数据,这些数据可能会产生您所看到的错误,并具有真正的内存不足。试试看Release能不能解决问题。

我只在 VC 上体验过这个,而不是 MinGW,但是我也没有检查过,这仍然可以解释问题。

于 2009-10-24T12:36:07.243 回答