Share via


CopyVolatileMemory 函式

CopyVolatileMemory 函式會將來源記憶體區塊的內容複製到目的地記憶體區塊。

重要

某些資訊與發行前版本產品有關,在發行前版本產品可能經過大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

參數

Param 目的地 [out]

所複製區塊目的地之起始位址的指標。

Param 來源 [in]

要複製之內存區塊起始位址的指標。

Param Length [in]

要複製的記憶體區塊大小,以位元組為單位。

語法

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

備註

此 API 存在以提供 CopyMemory 行為(亦即,將記憶體從某個位置複製到另一個位置),而開發人員必須確定複製作業發生時(亦即不受編譯程式優化的約束)。

API 具有下列屬性:

  • API 無法辨識為編譯程式內部函數,因此編譯程式永遠不會優化呼叫(完全或以「對等」指令序列取代呼叫)。 這與 CopyMemory 不同,這受限於各種編譯程序優化。
  • 呼叫傳回時,數據已從來源複製到目的地。 此函式記憶體存取 來源目的地 只會在函式內執行(亦即編譯程式無法將記憶體存取移出此函式)。
  • 如果平台允許,API 可能會執行未對齊的記憶體存取。
  • API 可能會在其複製作業中多次存取記憶體位置。
  • 類似於 CopyMemory,當 SourceDestination 彼此重疊時,它不支援複製作業。

注意

此函式適用於所有版本的 Windows,而不只是最新版本。 您必須取用最新的 SDK,才能從 winbase.h 標頭取得函式宣告。 您也需要來自最新 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
// CopyMemory/RtlCopyMemory so those functions are not guaranteed to actually
// make a local copy of data.
//
// CopyVolatileMemory does not handle a source/dest buffer that overlap
// with each other (CopyMemory 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;

CopyVolatileMemory(&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 RtlCopyMemory/RtlCopyMemory had been used to copy the data, it is possible
  // that a compiler may optimize away the call to CopyMemory 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

另請參閱