VirtualAlloc 関数 (memoryapi.h)
この記事の内容
呼び出し元プロセスの仮想アドレス空間内のページ領域の状態を予約、コミット、または変更します。 この関数によって割り当てられたメモリは、自動的に 0 に初期化されます。
別のプロセスのアドレス空間にメモリを割り当てるには、VirtualAllocEx 関数を使用します。
構文
LPVOID VirtualAlloc(
[in, optional] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flAllocationType,
[in] DWORD flProtect
);
パラメーター
[in, optional] lpAddress
割り当てるリージョンの開始アドレス。 メモリが予約されている場合、指定したアドレスは、割り当て粒度の最も近い倍数に切り捨てられます。 メモリが既に予約されていてコミットされている場合、アドレスは次のページ境界に切り捨てられます。 ホスト コンピューター上のページのサイズと割り当ての粒度を決定するには、GetSystemInfo 関数を使用します。 このパラメーターが NULL場合、システムは領域を割り当てる場所を決定します。
このアドレスが InitializeEnclave呼び出して初期化していないエンクレーブ内にある場合、VirtualAlloc は、そのアドレスのエンクレーブに 0 のページを割り当てます。 このページは以前はコミットされていない必要があり、Intel Software Guard Extensions プログラミング モデルの EEXTEND 命令では測定されません。
アドレスが初期化したエンクレーブ内にある場合、割り当て操作は ERROR_INVALID_ADDRESS エラーで失敗します。 これは、動的メモリ管理 (つまり SGX1) をサポートしていないエンクレーブに当てはまります。 SGX2 エンクレーブは割り当てを許可し、ページは割り当てられた後にエンクレーブによって受け入れられる必要があります。
[in] dwSize
リージョンのサイズ (バイト単位)。 lpAddress パラメーターが NULL場合、この値は次のページ境界に切り上げられます。 それ以外の場合、割り当てられたページには、lpAddress から dwSize lpAddress までの範囲の 1 つ以上のバイトを含むすべてのページが含まれます。 つまり、ページ境界にまたがる 2 バイト範囲では、両方のページが割り当てられた領域に含まれます。
[in] flAllocationType
メモリ割り当ての種類。 このパラメーターには、次のいずれかの値が含まれている必要があります。
価値
意味
MEM_COMMIT
0x00001000
指定された予約済みメモリ ページのメモリ使用量 (メモリの全体的なサイズとディスク上のページング ファイルから) を割り当てます。 また、この関数は、呼び出し元が最初にメモリにアクセスするときに、内容がゼロになることも保証します。 仮想アドレスが実際にアクセスされるまで、実際の物理ページは割り当てされません。
1 つのステップでページを予約してコミットするには、 VirtualAlloc を呼び出します。
MEM_RESERVE を指定せずに MEM_COMMIT を指定して特定のアドレス範囲をコミットしようとすると、以外の NULL lpAddress は、範囲全体が既に予約されていない限り失敗します。 結果のエラー コードは ERROR_INVALID_ADDRESS 。
既にコミットされているページをコミットしようとしても、関数は失敗しません。 つまり、各ページの現在のコミットメント状態を最初に判断することなく、ページをコミットできます。
lpAddress エンクレーブ内のアドレスを指定する場合は、flAllocationType MEM_COMMIT する必要があります。
MEM_RESERVE
0x00002000
メモリまたはディスク上のページング ファイル内の実際の物理ストレージを割り当てずに、プロセスの仮想アドレス空間の範囲を予約します。
VirtualAlloc 関数の後続の呼び出しで予約済みページをコミットできます。 1 つの手順でページを予約してコミットするには、MEM_COMMIT | MEM_RESERVE VirtualAlloc を呼び出します。
malloc や localAllocなど、他のメモリ割り当て関数では、解放されるまで予約されたメモリ範囲を使用できません。
MEM_RESET
0x00080000
lpAddress および dwSize で指定されたメモリ範囲内のデータが関心を持たなくなったことを示します。 ページをページング ファイルから読み取ったり、ページング ファイルに書き込んだりしないでください。 ただし、メモリ ブロックは後で再度使用されるため、デコミットしないでください。 この値は、他の値と共に使用することはできません。
この値を使用しても、MEM_RESET で操作される範囲にゼロが含まれるという保証はありません。 範囲にゼロを含める場合は、メモリをデコミットしてから、再コミットします。
MEM_RESET を指定すると、VirtualAlloc 関数は flProtectの値 無視します。 ただし、flProtect 有効な保護値 (PAGE_NOACCESS など) に設定する必要があります。
VirtualAlloc は、MEM_RESET を使用し、メモリの範囲がファイルにマップされている場合にエラーを返します。 共有ビューは、ページング ファイルにマップされている場合にのみ使用できます。
MEM_RESET_UNDO
0x1000000
MEM_RESET_UNDO は、MEM_RESET が以前に正常に適用されたアドレス範囲でのみ呼び出す必要があります。 これは、lpAddress および dwSize で指定された指定されたメモリ範囲内のデータが呼び出し元にとって重要であり、MEM_RESET の影響を取り消そうとしていることを示します。 関数が成功した場合は、指定したアドレス範囲のすべてのデータはそのままであることを意味します。 関数が失敗した場合、アドレス範囲のデータの少なくとも一部がゼロに置き換えられました。
この値は、他の値と共に使用することはできません。 前に MEM_RESET されなかったアドレス範囲で MEM_RESET_UNDO が呼び出された場合、動作は未定義です。 MEM_RESET を指定すると、VirtualAlloc 関数は flProtectの値 無視します。 ただし、flProtect 有効な保護値 (PAGE_NOACCESS など) に設定する必要があります。
Windows Server 2008 R2、Windows 7、Windows Server 2008、Windows Vista、Windows Server 2003、Windows XP: MEM_RESET_UNDO フラグは、Windows 8 および Windows Server 2012 までサポートされていません。
このパラメーターでは、次の値を指定することもできます。
価値
意味
MEM_LARGE_PAGES
0x20000000
大きなページ サポート使用してメモリを割り当てます。
サイズと配置は、大きなページの最小値の倍数である必要があります。 この値を取得するには、GetLargePageMinimum 関数を使用します。
この値を指定する場合は、MEM_RESERVE と MEM_COMMIT も指定する必要があります。
MEM_PHYSICAL
0x00400000
アドレスウィンドウ拡張 (AWE) ページ マップするために使用できるアドレス範囲を予約します。
この値は、MEM_RESERVE で使用する必要があり、他の値は使用できません。
MEM_TOP_DOWN
0x00100000
可能な限り高いアドレスでメモリを割り当てます。 これは、特に割り当てが多い場合に、通常の割り当てよりも遅くなる可能性があります。
MEM_WRITE_WATCH
0x00200000
割り当てられたリージョンに書き込まれたページをシステムが追跡します。 この値を指定する場合は、MEM_RESERVE も指定する必要があります。
リージョンが割り当てられたか、書き込み追跡状態がリセットされた後に書き込まれたページのアドレスを取得するには、getWriteWatch 関数 呼び出します。 書き込み追跡状態をリセットするには、GetWriteWatch 呼び出すか、ResetWriteWatchします。 書き込み追跡機能は、領域が解放されるまでメモリ領域に対して有効なままです。
[in] flProtect
割り当てるページの領域のメモリ保護。 ページをコミットする場合は、メモリ保護定数のいずれかを指定できます。
lpAddress エンクレーブ内のアドレスを指定する場合、flProtect 次の値を指定することはできません。
PAGE_NOACCESS
PAGE_GUARD
PAGE_NOCACHE
PAGE_WRITECOMBINE
エンクレーブに動的メモリを割り当てるときは、flProtect パラメーターを PAGE_READWRITE または PAGE_EXECUTE_READWRITE する必要があります。
戻り値
関数が成功した場合、戻り値はページの割り当てられた領域のベース アドレスです。
関数が失敗した場合、戻り値は NULL。 拡張エラー情報を取得するには、GetLastError 呼び出します。
各ページには、ページの状態関連付けられています。
VirtualAlloc 関数は、次の操作を実行できます。
予約ページのリージョンをコミットする
無料ページのリージョンを予約する
空きページの領域を同時に予約してコミットする
VirtualAlloc は予約ページを予約できません。 既にコミットされているページをコミットできます。 つまり、既にコミットされているかどうかに関係なく、ページの範囲をコミットでき、関数は失敗しません。
VirtualAlloc を使用してページブロックを予約し、その後、VirtualAlloc に対して追加の呼び出しを行って、予約ブロックから個々のページをコミットできます。 これにより、プロセスは、必要になるまで物理ストレージを消費することなく、その仮想アドレス空間の範囲を予約できます。
lpAddress パラメーターが NULLされていない場合、関数は lpAddress と dwSize パラメーターを使用して、割り当てるページの領域を計算します。 ページの範囲全体の現在の状態は、flAllocationType パラメーターで指定された割り当ての種類と互換性がある必要があります。 それ以外の場合、関数は失敗し、どのページも割り当てされません。 この互換性要件では、前に説明したように、既にコミット済みのページのコミットは除外されません。
動的に生成されたコードを実行するには、VirtualAlloc 使用してメモリを割り当て、VirtualProtect 関数を使用して PAGE_EXECUTE アクセスを許可します。
VirtualAlloc 関数を使用すると、指定されたプロセスの仮想アドレス空間内のメモリの アドレス ウィンドウ拡張 (AWE) 領域を予約できます。 その後、このメモリ領域を使用して、アプリケーションの必要に応じて、仮想メモリとの間で物理ページをマップできます。
MEM_PHYSICAL と MEM_RESERVE の値は、AllocationType パラメーターで設定する必要があります。
MEM_COMMIT 値は設定しないでください。 ページ保護を PAGE_READWRITE に設定する必要があります。
VirtualFree 関数は、コミットされたページのコミットを解除したり、ページのストレージを解放したり、コミットされたページを同時にデコミットして解放したりできます。 また、予約ページを解放して、無料のページにすることもできます。
実行可能なリージョンを作成する場合、呼び出し元のプログラムは、コードが設定されたら、FlushInstructionCache への適切な呼び出しによってキャッシュの一貫性を確保する責任を負います。 そうしないと、新しく実行可能なリージョンからコードを実行しようとすると、予期しない結果が発生する可能性があります。
例
例については、「メモリ の予約とコミット」を参照してください。
必要条件
要件
価値
サポートされる最小クライアント
Windows XP [デスクトップ アプリ |UWP アプリ]
サポートされる最小サーバー
Windows Server 2003 [デスクトップ アプリ |UWP アプリ]
ターゲット プラットフォーム の
ウィンドウズ
ヘッダー
memoryapi.h (Windows.h、Memoryapi.h を含む)
ライブラリ
onecore.lib
DLL
Kernel32.dll
関連項目
メモリ管理機能の
仮想メモリ関数 の
VirtualAllocEx の
VirtualFree
VirtualLock
VirtualProtect
VirtualQuery の
VBS エンクレーブ で使用できる Vertdll API