HeapCreate 函数 (heapapi.h)

创建可由调用进程使用的专用堆对象。 函数在进程的虚拟地址空间中保留空间,并为此块的指定初始部分分配物理存储。

语法

HANDLE HeapCreate(
  [in] DWORD  flOptions,
  [in] SIZE_T dwInitialSize,
  [in] SIZE_T dwMaximumSize
);

参数

[in] flOptions

堆分配选项。 这些选项通过调用堆函数影响对新堆的后续访问。 此参数可以是 0 或以下一个或多个值。

含义
HEAP_CREATE_ENABLE_EXECUTE
0x00040000
如果硬件强制实施 数据执行防护,则从此堆分配的所有内存块都允许代码执行。 在从堆运行代码的应用程序中使用此标志堆。 如果未指定 HEAP_CREATE_ENABLE_EXECUTE ,并且应用程序尝试从受保护的页面运行代码,则应用程序将收到异常,状态代码 STATUS_ACCESS_VIOLATION
HEAP_GENERATE_EXCEPTIONS
0x00000004
系统引发异常以指示失败 (例如,内存不足条件) 调用 HeapAllocHeapReAlloc 而不是返回 NULL
HEAP_NO_SERIALIZE
0x00000001
当堆函数访问此堆时,不使用序列化访问。 此选项适用于所有后续堆函数调用。 或者,可以在单个堆函数调用上指定此选项。

无法为使用此选项创建的堆启用低碎片化堆 (LFH) 。

不能锁定使用此选项创建的堆。

有关序列化访问的详细信息,请参阅本主题的“备注”部分。

[in] dwInitialSize

堆的初始大小(以字节为单位)。 此值确定为堆提交的初始内存量。 该值向上舍入为系统页面大小的倍数。 该值必须小于 dwMaximumSize

如果此参数为 0,则函数将提交一页。 若要确定主计算机上的页面大小,请使用 GetSystemInfo 函数。

[in] dwMaximumSize

堆的最大大小(以字节为单位)。 HeapCreate 函数将 dwMaximumSize 舍入到系统页大小的倍数,然后在堆的进程虚拟地址空间中保留该大小的块。 如果 HeapAllocHeapReAlloc 函数发出的分配请求超过 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,则堆会在调用过程中序列化访问。 当两个或多个线程同时尝试从同一堆分配或释放块时,序列化可确保相互排斥。 序列化的性能成本很小,但每当多个线程从同一个堆分配和释放内存时,必须使用它。 HeapLockHeapUnlock 函数可用于阻止和允许访问序列化堆。

设置 HEAP_NO_SERIALIZE 会消除堆上的相互排斥。 如果不进行序列化,使用同一堆句柄的两个或多个线程可能会尝试同时分配或释放内存,这可能会导致堆损坏。 因此, 只能在 以下情况下安全地使用HEAP_NO_SERIALIZE:

  • 进程只有一个线程。
  • 进程有多个线程,但只有一个线程调用特定堆的堆函数。
  • 进程具有多个线程,应用程序提供自己的机制,用于对特定堆进行相互排斥。

如果在使用 HEAP_NO_SERIALIZE 标志创建的堆上调用 HeapLockHeapUnlock 函数,则结果未定义。

若要获取进程的默认堆的句柄,请使用 GetProcessHeap 函数。 若要获取对调用进程处于活动状态的默认堆和专用堆的句柄,请使用 GetProcessHeaps 函数。

示例

枚举堆

要求

   
最低受支持的客户端 Windows XP [桌面应用 | UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 heapapi.h (包括 Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

另请参阅

堆函数

HeapAlloc

HeapDestroy

HeapValidate

内存管理函数

VBS enclave 中可用的 Vertdll API