次の方法で共有


MoveVolatileMemory 関数

コピー元メモリ ブロックの内容をコピー先メモリ ブロックにコピーします。コピー元とコピー先のメモリ ブロックの重複をサポートしています。

重要

一部の情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

パラメーター

パラメーター Destination [out]

コピーしたブロックのコピー先の開始アドレスへのポインター。

パラメーター Source [in]

コピーするメモリ ブロックの開始アドレスへのポインター。

パラメーター Length [in]

コピーするメモリ ブロックのサイズ (バイト単位)。

構文

volatile void* __cdecl
  MoveVolatileMemory (
    _Out_writes_bytes_all_(Length) volatile void* Destination,
    _In_reads_bytes_(Length) volatile const void* Source,
    SIZE_T Length
  );

解説

この API は、開発者がコピー操作を確実に行われるようにする必要がある (つまり、コンパイラの最適化の対象ではない) 場合に、MoveMemory の動作 (ある場所から別の場所にメモリをコピーする) を実現するために存在します。 CopyVolatileMemory とは異なり、この API は、Source バッファーと Destination バッファーが重複するケースを処理します。

この API には、次のプロパティがあります。

  • API はコンパイラの組み込みとして認識されないため、コンパイラは呼び出しを最適化して削除することはありません (呼び出しを完全に最適化するか、"同等の" 一連の命令に置き換えます)。 これは、さまざまなコンパイラ最適化の対象となる MoveMemory とは異なります。
  • 呼び出しが返されると、データは Source から Destination にコピーされています。 この関数の SourceDestination へのメモリ アクセスは、関数内でのみ実行されます (つまり、コンパイラはメモリ アクセスをこの関数の外に移動できません)。
  • プラットフォームで許可されている場合、API は整列されていないメモリ アクセスを実行することがあります。
  • API は、コピー操作の一環としてメモリ位置に複数回アクセスする場合があります。
  • MoveMemory と同様に、SourceDestination が互いに重複する場合のコピー操作をサポートしています

Note

この関数は、最新バージョンだけではなく、すべてのバージョンの Windows で動作します。 winbase.h ヘッダーから関数宣言を取得するには、最新の SDK を使う必要があります。 また、最新の SDK のライブラリ (volatileaccessu.lib) も必要です。 ですが、生成されたバイナリは、以前のバージョンの Windows でも問題なく動作します。

HEADER MyHeader;
UCHAR RawBuffer[100];

// Ensure that the shared memory (which could be constantly changing)
// is copied in to the local MyHeader variable.
// Note that the compiler is allowed to optimize away calls to
// MoveMemory/RtlMoveMemory so those functions are not guaranteed to actually
// make a local copy of data.
//
// MoveVolatileMemory does handle
// buffers that overlap with each other (MoveMemory semantics).
// Assume SharedMemory points to virtual memory that is also mapped in an untrusted process.
// Assume that untrusted process is changing the memory contents while you are accessing it.
PVOID SharedMemory;

MoveVolatileMemory(&MyHeader, SharedMemory, sizeof(MyHeader));

if (MyHeader.Size < 100) {
  // Because MyHeader is local and we are guaranteed we actually made
  // a local copy, we can be sure that the "Size" value will not change
  // between the previous bounds check and the below call to RtlFillMemory.
  // If RtlMoveMemory/RtlMoveMemory had been used to copy the data, it is possible
  // that a compiler may optimize away the call to MoveMemory and instead fetch
  // the “size” field of MyHeader directly from untrusted memory two times.
  // The first time it would be fetched for the bounds check, and the second
  // time it is fetched is for the call to FillMemory. It is possible the memory
  // could have changed between the two accesses resulting in the size check
  // being ineffective.

  FillMemory (RawBuffer, MyHeader.Size, 0);
}

要件

サポートされている最小のクライアント: Windows 11 Insider Preview ビルド TBD

ヘッダー: winbase.h (Winbase.h を含む)

カーネル モード ライブラリ: volatileaccessk.lib

ユーザー モード ライブラリ: volatileaccessu.lib

関連項目