2013-05-17 53 views
2

在一个应用程序中,我必须分配两个480 MB的缓冲区。内存分配使用HeapAlloc方法完成。该应用程序在没有运行多个应用程序的系统中工作正常。但是在其他应用程序也运行内存的系统中,由于连续内存不可用,未分配内存。尽管内存空间(非连续)可用,但未分配。连续内存分配

即使非连续内存可用,也需要帮助分配两个480 MB的缓冲区。

+1

你不能。添加更多的内存(交换或RAM),或使用非连续的容器,如['std :: deque'](http://en.cppreference.com/w/cpp/container/deque)。 –

+0

使用2个内存映射文件可以达到类似的结果吗?此时,系统管理内存,但你看到一个平坦的,连续的笨重的IIRC。 – JimR

+0

@JimR:这与真正的分配函数并没有什么不同,只是使用正常的分配函数时系统内存映射了页面文件,并且也知道您更愿意避免实际将更改写入磁盘。 –

回答

3

你所描述的情况在一个全功能的操作系统中是不可能的,它为每个进程提供了自己的地址空间。不管有多少其他应用程序正在运行,它们都不会影响进程中可用地址空间的连续性。虚拟内存可以将不连续的物理内存地址映射到虚拟地址空间中的连续范围。

只有在没有内存管理单元的嵌入式系统中,其他任务的存在才会导致程序遭受内存碎片。

HeapAlloc()建议Windows,它为每个进程提供一个单独的地址空间。最有可能的解释是,您的私有地址空间被分散在不同位置的库(DLL)碎片化。您可以重新绑定用于避免这种情况的库,并提供更大的连续地址空间块。

+0

用户空间vs内核空间vs物理内存。在我的程序员应该知道的事情清单上。 – Anthony

0

使用VirtualAlloc。支持虚拟页面的底层内存不需要是连续的,并且您将始终拥有完整的虚拟地址空间(32位系统上的2GB,我认为Windows x64上的8或16 TB,我不记得了。)HeapAlloc可以变成(通过您的流程使用,而不是其他)。您的地址空间也可能变得分散,所以请尽早在应用程序中分配它。实际上,我不推荐使用HeapAlloc,你可以使用new和delete(它调用malloc和free)。对于像你的malloc这样的大块,将在Windows上调用VirtualAlloc。

+2

'HeapAlloc'也会调用'VirtualAlloc' –

+0

我不知道,听起来像是地址空间碎片问题。正如你所说,可能是由加载的库引起的。 – Eloff

+0

好吧,显然这是堆创建时的一个选项。 “如果dwMaximumSize为0,那么堆的大小可能会增加,堆的大小仅受限于可用内存,为固定大小的堆分配大于限制的内存块的请求不会自动失败;相反,系统将调用VirtualAlloc函数来获取大块需要的内存。需要分配大内存块的应用程序应该将dwMaximumSize设置为0。 –

1

您可以使用VirtualAllocfAllocation指定为MEM_LARGE_PAGES。这使large page support,请注意,您必须检查GetLargePageMinimum,以确保系统支持大页面。

另请注意,由于此页面为details,因此速度可能会变慢。

由于每个大页面的物理空间必须是连续的,但内存可能已经变得碎片化,所以在系统长时间运行后,可能难以获取大页面内存区域。在这些条件下分配大页面可能会显着影响系统性能。因此,应用程序应该避免重复进行大页面分配,而应该在启动时一次分配所有大页面。

+0

单个页面的大小不会对此产生太大影响。在大型数组中进行随机访问时,需要大页面,因为页表中的每个条目都对应于更大部分的数据,因此需要的条目更少,并且更有可能适合翻译后备缓冲区(其作用与页表的缓存)。 –