Condividi tramite


Funzione MoveVolatileMemory

Copia il contenuto di un blocco di memoria di origine in un blocco di memoria di destinazione e supporta blocchi di memoria di origine e di destinazione sovrapposti.

Importante

Alcune informazioni riguardano un prodotto in versione preliminare che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Parametri

Destinazione param [out]

Puntatore all'indirizzo iniziale della destinazione del blocco copiato.

Origine param [in]

Puntatore all'indirizzo iniziale del blocco di memoria da copiare.

Lunghezza param [in]

Dimensione del blocco di memoria da copiare, in byte.

Sintassi

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

Osservazioni:

Questa API esiste per fornire il comportamento di MoveMemory (ad esempio, la copia della memoria da una posizione a un'altra) in situazioni in cui lo sviluppatore deve assicurarsi che l'operazione di copia si verifichi (ad esempio, non è soggetta alle ottimizzazioni del compilatore). A differenza di CopyVolatileMemory, questa API gestisce i casi in cui il buffer di origine e di destinazione si sovrappone.

L'API ha le proprietà seguenti:

  • L'API non viene riconosciuta come un compilatore intrinseco, quindi il compilatore non ottimizza mai la chiamata (interamente o sostituisce la chiamata con una sequenza di istruzioni "equivalente"). Questo comportamento è diverso da MoveMemory , soggetto a un'ampia gamma di ottimizzazioni del compilatore.
  • Al termine della chiamata, i dati sono stati copiati da Origine a Destinazione. Questa funzione consente l'accesso alla memoria all'origine e alla destinazione solo all'interno della funzione, ovvero il compilatore non può spostare gli accessi alla memoria da questa funzione.
  • L'API può eseguire accessi in memoria non idonei se la piattaforma lo consente.
  • L'API può accedere ai percorsi di memoria più di una volta come parte dell'operazione di copia.
  • Analogamente a MoveMemory in quanto supporta le operazioni di copia quando l'origine e la destinazione si sovrappongono tra loro

Nota

Questa funzione funziona su tutte le versioni di Windows, non solo sulla versione più recente. È necessario usare l'SDK più recente per ottenere la dichiarazione di funzione dall'intestazione winbase.h . È necessaria anche la libreria (volatileaccessu.lib) dall'SDK più recente. Tuttavia, il file binario risultante verrà eseguito correttamente nelle versioni precedenti di Windows.

Esempio

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);
}

Requisiti

Client minimo supportato: Windows 11 Insider Preview Build TBD

Intestazione: winbase.h (include Winbase.h)

Libreria in modalità kernel: volatileaccessk.lib

Libreria in modalità utente: volatileaccessu.lib

Vedi anche