HeapCreate 函数 (heapapi.h)
创建可由调用进程使用的专用堆对象。 函数在进程的虚拟地址空间中保留空间,并为此块的指定初始部分分配物理存储。
语法
HANDLE HeapCreate(
[in] DWORD flOptions,
[in] SIZE_T dwInitialSize,
[in] SIZE_T dwMaximumSize
);
参数
[in] flOptions
堆分配选项。 这些选项通过调用堆函数影响对新堆的后续访问。 此参数可以是 0 或以下一个或多个值。
值 | 含义 |
---|---|
|
如果硬件强制实施 数据执行防护,则从此堆分配的所有内存块都允许代码执行。 在从堆运行代码的应用程序中使用此标志堆。 如果未指定 HEAP_CREATE_ENABLE_EXECUTE ,并且应用程序尝试从受保护的页面运行代码,则应用程序将收到异常,状态代码 STATUS_ACCESS_VIOLATION。 |
|
系统引发异常以指示失败 (例如,内存不足条件) 调用 HeapAlloc 和 HeapReAlloc 而不是返回 NULL。 |
|
当堆函数访问此堆时,不使用序列化访问。 此选项适用于所有后续堆函数调用。 或者,可以在单个堆函数调用上指定此选项。
无法为使用此选项创建的堆启用低碎片化堆 (LFH) 。 不能锁定使用此选项创建的堆。 有关序列化访问的详细信息,请参阅本主题的“备注”部分。 |
[in] dwInitialSize
堆的初始大小(以字节为单位)。 此值确定为堆提交的初始内存量。 该值向上舍入为系统页面大小的倍数。 该值必须小于 dwMaximumSize。
如果此参数为 0,则函数将提交一页。 若要确定主计算机上的页面大小,请使用 GetSystemInfo 函数。
[in] dwMaximumSize
堆的最大大小(以字节为单位)。 HeapCreate 函数将 dwMaximumSize 舍入到系统页大小的倍数,然后在堆的进程虚拟地址空间中保留该大小的块。 如果 HeapAlloc 或 HeapReAlloc 函数发出的分配请求超过 dwInitialSize 指定的大小,系统会为堆提交额外的内存页,最大大小为堆的最大大小。
如果 dwMaximumSize 不为零,则堆大小是固定的,并且不能增长到超过最大大小。 此外,对于 32 位进程,可从堆中分配的最大内存块略小于 512 KB,而对于 64 位进程,则略低于 1,024 KB。 即使堆的最大大小足以包含块,分配较大块的请求也会失败。
如果 dwMaximumSize 为 0,堆大小可能会增大。 堆的大小仅受可用内存的限制。 分配大于固定大小堆限制的内存块的请求不会自动失败;相反,系统会调用 VirtualAlloc 函数来获取大型块所需的内存。 需要分配大量内存块的应用程序应将 dwMaximumSize 设置为 0。
返回值
如果函数成功,则返回值是新创建的堆的句柄。
如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。
注解
HeapCreate 函数创建一个专用堆对象,调用进程可以使用 HeapAlloc 函数从该对象分配内存块。 初始大小确定最初为堆分配的已提交页数。 最大大小确定保留页的总数。 这些页面在进程的虚拟地址空间中创建一个块,堆可以增长到其中。 如果 HeapAlloc 的请求超过已提交页面的当前大小,则如果物理存储可用,则会自动从此预留空间提交其他页面。
Windows Server 2003 和 Windows XP: 默认情况下,新创建的专用堆是标准堆。 若要启用低碎片堆,请使用专用堆的句柄调用 HeapSetInformation 函数。
专用堆对象的内存只能由创建它的进程访问。 如果动态链接库 (DLL) 创建专用堆,则会在调用 DLL 的进程地址空间中创建堆,并且只有该进程才能访问该堆。
系统使用专用堆中的内存来存储堆支持结构,因此并非所有指定的堆大小都可供进程使用。 例如,如果 HeapAlloc 函数从最大大小为 64K 的堆请求 64 KB (K) ,则请求可能会因系统开销而失败。
如果未在简单默认) (指定HEAP_NO_SERIALIZE,则堆会在调用过程中序列化访问。 当两个或多个线程同时尝试从同一堆分配或释放块时,序列化可确保相互排斥。 序列化的性能成本很小,但每当多个线程从同一个堆分配和释放内存时,必须使用它。 HeapLock 和 HeapUnlock 函数可用于阻止和允许访问序列化堆。
设置 HEAP_NO_SERIALIZE 会消除堆上的相互排斥。 如果不进行序列化,使用同一堆句柄的两个或多个线程可能会尝试同时分配或释放内存,这可能会导致堆损坏。 因此, 只能在 以下情况下安全地使用HEAP_NO_SERIALIZE:
- 进程只有一个线程。
- 进程有多个线程,但只有一个线程调用特定堆的堆函数。
- 进程具有多个线程,应用程序提供自己的机制,用于对特定堆进行相互排斥。
如果在使用 HEAP_NO_SERIALIZE 标志创建的堆上调用 HeapLock 和 HeapUnlock 函数,则结果未定义。
若要获取进程的默认堆的句柄,请使用 GetProcessHeap 函数。 若要获取对调用进程处于活动状态的默认堆和专用堆的句柄,请使用 GetProcessHeaps 函数。
示例
要求
最低受支持的客户端 | Windows XP [桌面应用 | UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | heapapi.h (包括 Windows.h) |
Library | Kernel32.lib |
DLL | Kernel32.dll |