Winapi malloc返回NULL并将errno设置为ENOMEM,但是有足够的堆空间可用吗?

Winapi malloc返回NULL并将errno设置为ENOMEM,但是有足够的堆空间可用吗?,winapi,malloc,crt,heapalloc,enomem,Winapi,Malloc,Crt,Heapalloc,Enomem,我遇到这样一种情况,malloc()返回NULL并将errno设置为ENOMEM。但是CRT堆(可扩展)有大量内存可供使用。在malloc时,我的进程内存约为900 MB。主机进程是在Sun HotSpot JVM下执行的Java可执行文件 我正在做的malloc()。如果我分配60 MB,它就会成功。在那之后,一个50MB的分配,接着是另一个,另一个也成功了:显然,我仍然有很多内存,但是80MB的malloc看起来太“大”了,操作系统无法消化 我使用的是Windows7x64SP1,内存为4G

我遇到这样一种情况,
malloc()
返回
NULL
并将
errno
设置为
ENOMEM
。但是CRT堆(可扩展)有大量内存可供使用。在
malloc
时,我的进程内存约为900 MB。主机进程是在Sun HotSpot JVM下执行的Java可执行文件

我正在做的
malloc()。如果我分配60 MB,它就会成功。在那之后,一个50MB的分配,接着是另一个,另一个也成功了:显然,我仍然有很多内存,但是80MB的malloc看起来太“大”了,操作系统无法消化

我使用的是Windows7x64SP1,内存为4GB。我的进程是一个32位进程,使用VC++2010 SP1构建。我使用的是低碎片堆,这是Win7上的默认值-我也用HeapQueryInformation进行了验证。 我使用的VC2010 C运行时以以下方式创建堆:

HeapCreate(0, BYTES_PER_PAGE, 0)
根据
HeapCreate
的文档,
HeapAlloc
将自动调用
VirtualAlloc
处理大于512KB的块

如果不是内存不足,是什么原因导致
malloc()
失败?我的记忆是不是太零碎了?我以为Windows会自动压缩堆。 这真的很奇怪,我以前从未见过这种行为

另一台Windows XP SP3 32位计算机也表现出同样的行为

谢谢,
Martin

可能与此相关,即没有足够的连续内存。是的,地址空间碎片会导致这种情况。900 MB对于失败来说太早了,您可能正在查看工作集,而不是VM大小。SysInternals的VMMap实用程序很有用。虽然64位操作系统是一个微不足道的解决方案,但在其他方面并不容易修复。Hans,我所说的900 MB是Windows任务管理器的“内存(专用工作集)”值。此外,“峰值工作集(内存)”列的值约为910MB。根据CRT函数_heapwalk(),此时CRT堆的总大小约为280MB。私有Java堆的大小是330 MB,这是有道理的,因为我明确指定了330 MB用于Java堆。考虑到我的峰值内存使用量只有910 MB,我非常惊讶操作系统不能遵守我的80 MB分配,因为我应该有1.1 GB未使用、未触及的进程内存可用。然而,我猜操作系统在整个2GB地址空间中分配了900MB,也许我非常不幸,在整个2GB地址空间中没有一个连续的80MB块可用?!!!请大家不要让我失望:(我有更多信息。我运行Process Explorer,当malloc失败时,虚拟内存属性如下:-私有字节:900 MB-峰值私有字节:910 MB-虚拟大小:1.5 GB(我想这就是我们谈论的虚拟机大小)在Windows 7 x64上使用带有LargeAddressWare标志的32位Java虚拟机运行我的应用程序时,最大虚拟地址空间大小(VM大小)为4 GB,而不是2 GB。而且应用程序确实运行良好。