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
ヒープの省略可能な属性を指定するフラグ。 これらのオプションは、ヒープ関数 (RtlAllocateHeap と RtlFreeHeap) の呼び出しを通じて、後続の新しいヒープへのアクセスに影響します。
省略可能な属性が要求されない場合、呼び出し元はこのパラメーターを 0 に設定する必要があります。
このパラメーターには、次の 1 つ以上の値を指定できます。
値 | 意味 |
---|---|
HEAP_GENERATE_EXCEPTIONS | NULL を返す代わりに、STATUS_NO_MEMORYなどの例外を発生させることによって、システムがヒープ エラーを示すように指定します。 |
HEAP_GROWABLE | ヒープが拡張可能であることを指定します。 HeapBase が NULL の場合は、指定する必要があります。 |
HEAP_NO_SERIALIZE | ヒープ関数がこのヒープからメモリを割り当てて解放するときに、相互除外を使用しないことを指定します。 既定では、HEAP_NO_SERIALIZEが指定されていない場合は、ヒープへのアクセスをシリアル化します。 ヒープ アクセスのシリアル化により、2 つ以上のスレッドが同じヒープから同時にメモリを割り当てて解放できます。 |
[in, optional] HeapBase
次の 2 つのアクションのいずれかを指定します。
HeapBase が NULL 以外の値の場合は、ヒープに使用する呼び出し元によって割り当てられたメモリのブロックのベース アドレスを指定します。
HeapBase が NULL の場合、RtlCreateHeap はプロセスの仮想アドレス空間からヒープのシステム メモリを割り当てます。
[in, optional] ReserveSize
ReserveSize が 0 以外の値の場合、ヒープ用に予約するメモリの初期量をバイト単位で指定します。 RtlCreateHeap は ReserveSize を次のページ境界に切り上げ、そのサイズのブロックをヒープ用に予約します。
このパラメーターは省略可能であり、0 にすることができます。 次の表は、 ReserveSize パラメーターと CommitSize パラメーターの相互作用をまとめたものです。
値 | 結果 |
---|---|
ReserveSize 0、 CommitSize 0 | 最初はヒープ用に 64 ページが予約されています。 1 つのページが最初にコミットされます。 |
ReserveSize 0、 CommitSize 0 以外 | RtlCreateHeap は ReserveSize を CommitSize に設定し、 ReserveSize を最も近い倍数 (PAGE_SIZE * 16) に丸めます。 |
ReserveSize 0 以外、 CommitSize 0 | 最初は、ヒープに対して 1 つのページがコミットされます。 |
ReserveSize 0 以外、 CommitSize 0 以外 | CommitSize が ReserveSize より大きい場合、RtlCreateHeapは CommitSize を ReserveSize に減らします。 |
[in, optional] CommitSize
CommitSize が 0 以外の値の場合、ヒープにコミットするメモリの初期量 (バイト単位) を指定します。 RtlCreateHeapは CommitSize を次のページ境界に切り上げ、ヒープのプロセスの仮想アドレス空間でそのサイズのブロックをコミットします。
このパラメーターは省略可能であり、0 にすることができます。
[in, optional] Lock
リソース ロックとして使用される不透明な ERESOURCE 構造体へのポインター。 このパラメーターは省略可能であり、NULL にすることができます。 呼び出し元によって指定された場合、構造体は非ページ プールから割り当て、 ExInitializeResourceLite または ExReinitializeResourceLite を呼び出して初期化 する必要があります。 HEAP_NO_SERIALIZE フラグが設定されている場合、このパラメーターは NULL である必要があります。
[in, optional] Parameters
ヒープの作成時に適用されるパラメーターを含む RTL_HEAP_PARAMETERS 構造体へのポインター。 このパラメーターは省略可能であり、NULL にすることができます。
戻り値
RtlCreateHeap は、作成されたヒープへのアクセスに使用するハンドルを返します。
注釈
RtlCreateHeap は、呼び出し元プロセスが RtlAllocateHeap を呼び出すことによってメモリ ブロックを割り当てることができるプライベート ヒープ オブジェクトを作成します。 初期コミット サイズは、ヒープに最初に割り当てられたページ数を決定します。 初期予約サイズによって、ヒープ用に最初に予約されたページ数が決まります。 予約されているがコミットされていないページは、ヒープを展開できるプロセスの仮想アドレス空間にブロックを作成します。
RtlAllocateHeap によって行われた割り当て要求がヒープの初期コミット サイズを超えた場合、システムはヒープの物理ストレージの追加ページをヒープの最大サイズまでコミットします。 ヒープが拡張できない場合、その最大サイズは初期予約サイズに制限されます。
ヒープが拡張可能な場合、そのサイズは使用可能なメモリによってのみ制限されます。 RtlAllocateHeap による要求がコミットされたページの現在のサイズを超える場合、システムは ZwAllocateVirtualMemory を呼び出して、必要なメモリを取得します(物理ストレージが使用可能であると仮定)。
さらに、ヒープが拡張できない場合は、絶対的な制限が発生します。ヒープ内のメモリ ブロックの最大サイズは0x7F000 バイトです。 ヒープの仮想メモリしきい値は、最大ヒープ ブロック サイズまたは Parameters 構造体の VirtualMemoryThreshold メンバーの値のいずれか小さい方に等しくなります。 また、ヒープの最大サイズがブロックを格納するのに十分な大きさであっても、要求サイズをメタデータとアラインメントのために埋め込む必要がある場合もあります。 そのため、VirtualMemoryThreshold の 4096 バイト (1 ページ) 以内にブロックを割り当てる要求が失敗する可能性があります。 (VirtualMemoryThreshold の詳細については、RtlCreateHeap の Parameters パラメーターのメンバーを参照してください)。
ヒープが拡張可能な場合、ヒープの仮想メモリしきい値を超えるブロックを割り当てる要求は自動的に失敗しません。システムは ZwAllocateVirtualMemory を呼び出して、このような大きなブロックに必要なメモリを取得します。
プライベート ヒープ オブジェクトのメモリには、それを作成したプロセスのみがアクセスできます。
システムはプライベート ヒープのメモリを使用してヒープ サポート構造を格納するため、指定されたすべてのヒープ サイズをプロセスで使用できるわけではありません。 たとえば、 RtlAllocateHeap が最大サイズが 64K のヒープから 64 キロバイト (K) を要求した場合、システム オーバーヘッドが原因で要求が失敗する可能性があります。
HEAP_NO_SERIALIZEが指定されていない場合 (単純な既定値)、ヒープは呼び出し元のプロセス内でアクセスをシリアル化します。 シリアル化により、2 つ以上のスレッドが同じヒープからブロックを同時に割り当てたり解放したりしようとすると、相互の除外が保証されます。 シリアル化にはパフォーマンス コストは小さくなりますが、複数のスレッドが同じヒープからメモリを割り当てて解放するたびに使用する必要があります。
HEAP_NO_SERIALIZE設定すると、ヒープの相互除外がなくなります。 シリアル化を行わないと、同じヒープ ハンドルを使用する 2 つ以上のスレッドが同時にメモリの割り当てまたは解放を試みる可能性があり、ヒープが破損する可能性があります。 したがって、HEAP_NO_SERIALIZEは、次の状況でのみ安全に使用できます。
プロセスに含まれるスレッドは 1 つだけです。
プロセスには複数のスレッドがありますが、特定のヒープのヒープ関数を呼び出すスレッドは 1 つだけです。
プロセスには複数のスレッドがあり、アプリケーションは特定のヒープに対する相互除外のための独自のメカニズムを提供します。
注意
アクセス違反から保護するには、構造化例外処理を使用して、ヒープへの書き込みまたはヒープからの読み取りを行うコードを保護します。 メモリ アクセスを使用した構造化例外処理の詳細については、「例外の 処理**」を参照してください。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows XP |
対象プラットフォーム | ユニバーサル |
Header | ntifs.h (Ntifs.h を含む) |
Library | Ntoskrnl.lib |
[DLL] | NtosKrnl.exe (カーネル モード);Ntdll.dll (ユーザー モード) |
IRQL | < DISPATCH_LEVEL |