我遇到了一个奇怪的问题,我的进程无法分配比看起来略低于1 GiB的数据。当我的软件发出bad_alloc
异常时,Windows任务管理器“内存使用情况”列显示接近1 GiB的值。是的,我检查传递给内存分配的值是否合理。 (不存在会导致此失败的竞争条件/腐败)。是的,我需要所有这些记忆而没有办法解决它。 (它是图像的缓冲区,无法进一步压缩)
我不打算一次性分配整个1 GiB内存,有几个分配大约300 MiB。这会引起问题吗? (我会试着看看更小的分配是否更好)。是否有一些编译器开关或我必须设置的其他东西才能超过1 GiB?我见过其他人抱怨2 GiB限制,这对我来说没问题。我只需要多一点:)。我正在使用VS 2005和SP1,我在32位XP上运行它,它是用C ++编写的。
答案 0 :(得分:11)
在32位操作系统上,进程总共有4GB的地址空间 。
在Windows上,其中一半是禁止的,因此您的进程有2GB。
这是2GB的连续内存。但它变得支离破碎。您的可执行文件在一个地址加载,每个DLL加载到另一个地址,然后是堆栈,堆分配等等。因此,虽然您的进程可能有足够的空闲地址空间,但是没有足够大的连续块来满足您的内存请求。因此,进行较小的分配可能会解决它。
如果您的应用程序是使用LARGEADDRESSAWARE标志编译的,那么它将允许使用尽可能多的剩余2GB内容,因为Windows可以备用。 (其价值取决于您的平台和环境。
所以,如果您的应用程序可以处理它(它基本上是一个功能标志),设置标志总是一个好主意。它告诉Windows 我们可以处理更多内存,所以如果Windows也可以,它应该继续,并尽可能地给我们一个大的地址空间),但你可能不能依赖它有效果。除非您使用的是64位操作系统,否则不太可能为您买单。 (/ 3GB启动开关是必需的,并且已知会导致驱动程序出现问题,尤其是视频驱动程序)
答案 1 :(得分:4)
分配大块连续内存总是一个问题。 它很可能在较小的块中获得更多内存
你应该重新设计你的记忆结构。
答案 2 :(得分:2)
你怀疑更大的300MB分配是正确的。您的进程将能够接近2GB(如果使用/ 3GB boot.ini开关和LARGEADDRESSAWARE链接标志,则为3),但不能作为一个大的连续块。
这方面的典型解决方案是将请求分解为固定大小的磁贴或条带(例如256x256x4字节),并编写一个中间类来隐藏此表示细节。
您可以通过编写一个分配不同大小的块的小分配循环来快速验证这一点。
答案 3 :(得分:1)
您还可以从MSDN检查this功能。 1GB从这里响铃:
此参数必须大于或等于13页(例如, 在具有4K页面大小的系统上为53,248,并且小于系统范围 最大值(可用页数减去512页)。默认大小 是345页(例如,在具有a的系统上,这是1,413,120字节 4K页面大小)。
他们在这里提到过程允许的默认最大页数为345页,略高于1GB。
答案 4 :(得分:0)
当我有一些像这样的大型alloc时,我使用Windows函数VirtualAlloc,以避免对默认分配器施加压力。
另一种方法可能是在项目中使用nedmalloc。