背景:我写C++程序的工作有大量地理数据,并希望载大块来处理在一个单一的去。我是约束作用的应用程序编制为32位的机器。机器我测试上运行的64位的操作系统(Windows7),有6个演出。使用MS VS2008年。

我有下列代码:

byte* pTempBuffer2[3];
try
{
    //size_t nBufSize = nBandBytes*m_nBandCount;
    pTempBuffer2[0] = new byte[nBandBytes];
    pTempBuffer2[1] = new byte[nBandBytes];
    pTempBuffer2[2] = new byte[nBandBytes];
}
catch (std::bad_alloc)
{
    // If we didn't get the memory just don't buffer and we will get data one
    // piece at a time.
    return;
}

我希望,我将能够分配存储直到应用程序,达到了4千兆字节的限制的32位处理的问题。然而,当nBandBytes是466,560,000新抛出std::bad_alloc在第二次尝试。在这个阶段,工作组(存储器)的价值的过程665,232K因此,我似乎不可能获得甚至演出的内存进行分配。

已有一些提及的2演出限制对应用程序中的32位Windows其可扩展到3演出与/3GB开关于win32.这是很好的建议下,环境,但是没有关于这种情况。

有多少内存你应该能分配下的64位系统,一个32位的应用程序?

有帮助吗?

解决方案

尽OS想给你。默认情况下,窗户可以让一个32位进程有2GB的地址空间。和这个被分割成几块。一个区域设置一旁的堆,其他每个执行和dll装载。不管是什么离开可以是动态分配,但是,没有任何保证,这将是一个很大的毗连区块。这可能是若干较小的区块的几百MB的每一个。

如果你汇编与LargeAddressAware标志,64位Windows会让你使用全4G地址的空间,这应该有助于一位,但在一般情况下,

  • 你不应该假定可用的存储器是连续的。你应该能够与多个较小的分配,而不是几个大的,
  • 你应当汇编它作为64-位应用程序,如果你需要大量的存储器。

其他提示

在Windows 32位上,正常进程最多可以占用2 GB,但使用 / 3GB 切换它可以达到3 GB(对于Windows 2003)。

但在你的情况下,我认为你正在分配连续的内存,所以发生了异常。

您可以分配尽可能多的内存,因为您的页面文件可以让您 - 即使没有/ 3GB开关,您也可以毫不费力地分配4GB的内存。

阅读本文概述了如何考虑物理内存,虚拟内存和地址空间(这三者都是不同的东西)。简而言之,您拥有与RAM相同的物理内存,但您的应用程序根本没有与该物理内存的交互 - 它只是存储虚拟内存中数据的便利位置。您的虚拟内存受页面文件大小的限制,应用程序可以使用的数量受其他应用程序使用量的限制(尽管您可以分配更多,但实际上并未使用它)。您在32位世界中的地址空间是4GB。其中,2 GB分配给内核(如果使用/ 3BG交换机,则为1 GB)。剩下的2GB中,有些会被你的堆栈耗尽,有些会被你正在运行的程序(以及所有的dll等等)用完。它会变得支离破碎,而你只能获得如此多的连续空间 - 这就是你的分配失败的地方。但是,由于该地址空间只是访问您为自己分配的虚拟内存的一种便捷方式,因此可以分配更多内存,并将其中的大块内容一次性地添加到您的地址空间中。

Raymond Chen有一个例子分配4GB内存并将其中的一部分映射到地址空间的一部分。

在32位Windows下,64位Windows中的最大可分配容量为16TB和256TB。

如果你真的了解内存管理在Windows中的运作方式,请阅读这篇文章

在ElephantsDream项目期间,Blender Foundation与Blender 3D有类似的问题(尽管在Mac上)。不能包含链接但谷歌:blender3d内存分配问题,它将是第一项。

解决方案涉及文件映射。我自己没试过,但你可以在这里阅读: http://msdn.microsoft.com/en-us/library/aa366556(VS.85)的.aspx

nBandBytes为466,560,000,您尝试分配1.4 GB。 32位应用程序通常只能访问2 GB的内存(如果使用/ 3GB启动,则会更多,并且可执行文件被标记为可识别大地址空间)。您可能很难为大块内存找到许多连续的地址空间块。

如果要在64位操作系统上分配千兆字节的内存,请使用64位进程。

您应该能够为每个进程分配大约2GB的空间。 这篇文章(PDF)解释细节。但是,您可能无法获得一个甚至接近那么大的连续块。

即使您分配较小的块,也无法获得所需的内存,特别是如果周围的程序具有不可预测的内存行为,或者您需要在不同的操作系统上运行。根据我的经验,32位进程的堆空间大约为1.2GB。

在这个内存量,我建议手动写入磁盘。将数组包装在管理内存的类中,并在必要时写入临时文件。希望您的程序的特性能够有效地缓存部分数据,而不会过多地占用磁盘。

Sysinternals VMMap 非常适合调查虚拟地址空间碎片,这可能会限制您可以分配多少连续内存。我建议将其设置为显示可用空间,然后按大小排序以找到最大的空闲区域,然后按地址排序以查看分隔最大空闲区域(可能是重新定位的DLL,共享内存区域或其他堆)的内容。

正如其他人所建议的那样,避免极大的连续分配可能是最好的。

设置 LARGE_ADDRESS_AWARE = YES (如jalf建议的那样)是好的,只要应用程序所依赖的库与它兼容即可。如果您这样做,则应使用 <来测试您的代码。 code> AllocationPreference 注册表项设置为启用自上而下的虚拟地址分配。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top