共用方式為


RtlCreateHeap 函式 (ntifs.h)

RtlCreateHeap 例程會建立可由呼叫進程使用的堆積物件。 此例程會在進程的虛擬位址空間中保留空間,並為此區塊的指定初始部分配置實體記憶體。

語法

NTSYSAPI PVOID RtlCreateHeap(
  [in]           ULONG                Flags,
  [in, optional] PVOID                HeapBase,
  [in, optional] SIZE_T               ReserveSize,
  [in, optional] SIZE_T               CommitSize,
  [in, optional] PVOID                Lock,
  [in, optional] PRTL_HEAP_PARAMETERS Parameters
);

參數

[in] Flags

指定堆積選擇性屬性的旗標。 這些選項會透過呼叫堆積函式來影響對新堆積的後續存取(RtlAllocateHeapRtlFreeHeap)。

如果沒有要求選擇性屬性,呼叫端應該將此參數設定為零。

此參數可以是下列其中一或多個值。

價值 意義
HEAP_GENERATE_EXCEPTIONS 指定系統會藉由引發例外狀況來指出堆積失敗,例如STATUS_NO_MEMORY,而不是傳回NULL。
HEAP_GROWABLE 指定堆積可成長。 如果 heapBase 為 NULL,則必須指定 HeapBase。
HEAP_NO_SERIALIZE 指定堆積函式配置和釋放此堆積中的記憶體時,不會使用相互排除。 未指定HEAP_NO_SERIALIZE時,預設值是串行化堆積的存取權。 堆積存取的串行化可讓兩個或多個線程同時配置和釋放來自相同堆積的記憶體。

[in, optional] HeapBase

指定兩個動作的其中一個:

如果 HeapBase 為非 NULL 值,它會指定呼叫端配置記憶體區塊的基位址,以用於堆積。

如果 HeapBase 為 NULL,RtlCreateHeap 從進程的虛擬位址空間配置堆積的系統記憶體。

[in, optional] ReserveSize

如果 ReserveSize 為非零值,它會指定堆積保留的初始記憶體數量,以位元組為單位。 RtlCreateHeap 會四捨五入 ReserveSize 到下一個頁面界限,然後保留堆積大小的區塊。

這個參數是選擇性的,而且可以是零。 下表摘要說明 ReserveSizeCommitSize 參數的互動。

結果
ReserveSize 零,CommitSize 64 頁最初會保留給堆積。 一頁一開始會認可。
ReserveSize 零,CommitSize 非零 RtlCreateHeap 會設定 ReserveSize 等於 commitSize,然後將 ReserveSize 四捨五入至最接近的倍數 (PAGE_SIZE * 16)。
ReserveSize 非零,CommitSize 一頁一開始會針對堆積認可。
ReserveSize 非零,CommitSize 非零 如果 CommitSize 大於 ReserveSizeRtlCreateHeap 會減少 CommitSizeReserveSize

[in, optional] CommitSize

如果 CommitSize 為非零值,它會指定要認可堆積的初始記憶體數量,以位元組為單位。 RtlCreateHeap 會四捨五入 CommitSize 到下一個頁面界限,然後在處理程式的虛擬位址空間中認可該大小的區塊。

這個參數是選擇性的,而且可以是零。

[in, optional] Lock

要當做資源鎖定使用之不透明 ERESOURCE 結構的指標。 這個參數是選擇性的,而且可以是 NULL。 由呼叫端提供時,結構必須從非分頁集區配置,並藉由呼叫 exInitializeResourceLiteExReinitializeResourceLite初始化。 如果已設定HEAP_NO_SERIALIZE旗標,此參數必須是 NULL。

[in, optional] Parameters

RTL_HEAP_PARAMETERS 結構的指標,其中包含建立堆積時要套用的參數。 這個參數是選擇性的,而且可以是 NULL。

傳回值

RtlCreateHeap 會傳回用來存取已建立堆積的句柄。

言論

RtlCreateHeap 會建立私人堆積物件,呼叫進程可以從中呼叫 RtlAllocateHeap來配置記憶體區塊。 初始認可大小會決定最初為堆積配置的頁面數目。 初始保留大小決定最初保留給堆積的頁面數目。 保留但未認可的頁面會在程式的虛擬位址空間中建立區塊,堆積可以擴充到其中。

如果 RtlAllocateHeap 所提出的配置要求 超過堆積的初始認可大小,則系統會認可堆積的其他實體記憶體頁面,最多可達堆積的大小上限。 如果堆積無法成長,其大小上限會限制為其初始保留大小。

如果堆積可成長,其大小只會受限於可用的記憶體。 如果 RtlAllocateHeap 的要求 超過目前認可的頁面大小,系統會呼叫 ZwAllocateVirtualMemory 以取得所需的記憶體,假設實體記憶體可用。

此外,如果堆積無法成長,就會發生絕對限制:堆積中記憶體區塊的大小上限為0x7F000個字節。 堆積的虛擬記憶體臨界值等於堆積區塊大小上限,或 VirtualMemoryThresholdParameters 結構成員的值,以較小者為準。 堆積可能也需要填補元數據和對齊目的的要求大小,因此要求在 VirtualMemoryThres hold 的 4096 位元組 (1 Page) 內配置區塊的要求,即使堆積的大小上限足以包含區塊,仍可能會失敗。 (如需 virtualMemoryThreshold的詳細資訊,請參閱 RtlCreateHeap 參數的成員。

如果堆積可成長,配置大於堆積虛擬記憶體臨界值之區塊的要求不會自動失敗;系統會呼叫 ZwAllocateVirtualMemory,以取得這類大型區塊所需的記憶體。

私人堆積物件的記憶體只能存取建立它的進程。

系統會使用私人堆積中的記憶體來儲存堆積支持結構,因此並非所有指定的堆積大小都可供進程使用。 例如,如果 RtlAllocateHeap 從大小上限為 64K 的堆積要求 64 KB,要求可能會因為系統額外負荷而失敗。

如果未指定HEAP_NO_SERIALIZE (簡單預設值),堆積將會串行化呼叫程式中的存取權。 當兩個或多個線程嘗試同時配置或釋放來自相同堆積的區塊時,串行化可確保相互排除。 串行化需要少量的效能成本,但每當多個線程從相同的堆積配置和釋放記憶體時,都必須使用它。

設定HEAP_NO_SERIALIZE可排除堆積上的相互排除。 如果沒有串行化,使用相同堆積句柄的兩個或多個線程可能會同時嘗試配置或釋放記憶體,這可能會導致堆積損毀。 因此,HEAP_NO_SERIALIZE只能在下列情況下安全地使用:

  • 進程只有一個線程。

  • 進程有多個線程,但只有一個線程會呼叫特定堆積的堆積函式。

  • 進程有多個線程,而且應用程式會提供自己的機制,以相互排除至特定堆積。

注意

若要防範存取違規,請使用結構化例外狀況處理來保護寫入或讀取堆積的任何程序代碼。 如需使用記憶體存取進行結構化例外狀況處理的詳細資訊,請參閱 處理例外狀況**

要求

要求 價值
最低支援的用戶端 Windows XP
目標平臺 普遍
標頭 ntifs.h (include Ntifs.h)
連結庫 Ntoskrnl.lib
DLL NtosKrnl.exe (核心模式):Ntdll.dll (使用者模式)
IRQL < DISPATCH_LEVEL

另請參閱

RtlAllocateHeap

RtlDestroyHeap

RtlFreeHeap