Création de pages Guard

Une page de protection fournit une alarme one-shot pour l’accès à la page mémoire. Cela peut être utile pour une application qui doit surveiller la croissance de grandes structures de données dynamiques. Par exemple, il existe des systèmes d’exploitation qui utilisent des pages de protection pour implémenter la vérification automatique de la pile.

Pour créer une page de protection, définissez le modificateur PAGE_GUARD protection de page pour la page. Cette valeur peut être spécifiée, ainsi que d’autres modificateurs de protection de page, dans les fonctions VirtualAlloc, VirtualAllocEx, VirtualProtect et VirtualProtectEx . Le modificateur de PAGE_GUARD peut être utilisé avec n’importe quel autre modificateur de protection de page, à l’exception de PAGE_NOACCESS.

Si un programme tente d’accéder à une adresse dans une page de protection, le système déclenche une exception STATUS_GUARD_PAGE_VIOLATION (0x80000001). Le système efface également le modificateur PAGE_GUARD, en supprimant la page de protection de la page mémoire status. Le système n’arrêtera pas la prochaine tentative d’accès à la page mémoire avec une exception STATUS_GUARD_PAGE_VIOLATION .

Si une exception de page de protection se produit pendant un service système, le service échoue et retourne généralement un indicateur d’échec status. Étant donné que le système supprime également la page de protection de la page de mémoire appropriée status, l’appel suivant du même service système n’échouera pas en raison d’une exception STATUS_GUARD_PAGE_VIOLATION (sauf, bien sûr, si quelqu’un rétablit la page de protection).

Le programme court suivant illustre le comportement de la protection des pages de protection.

/* A program to demonstrate the use of guard pages of memory. Allocate
   a page of memory as a guard page, then try to access the page. That
   will fail, but doing so releases the lock on the guard page, so the
   next access works correctly.

   The output will look like this. The actual address may vary.

   This computer has a page size of 4096.
   Committed 4096 bytes at address 0x00520000
   Cannot lock at 00520000, error = 0x80000001
   2nd Lock Achieved at 00520000

   This sample does not show how to use the guard page fault to
   "grow" a dynamic array, such as a stack. */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>

int main()
{
  LPVOID lpvAddr;               // address of the test memory
  DWORD dwPageSize;             // amount of memory to allocate.
  BOOL bLocked;                 // address of the guarded memory
  SYSTEM_INFO sSysInfo;         // useful information about the system

  GetSystemInfo(&sSysInfo);     // initialize the structure

  _tprintf(TEXT("This computer has page size %d.\n"), sSysInfo.dwPageSize);

  dwPageSize = sSysInfo.dwPageSize;

  // Try to allocate the memory.

  lpvAddr = VirtualAlloc(NULL, dwPageSize,
                         MEM_RESERVE | MEM_COMMIT,
                         PAGE_READONLY | PAGE_GUARD);

  if(lpvAddr == NULL) {
    _tprintf(TEXT("VirtualAlloc failed. Error: %ld\n"),
             GetLastError());
    return 1;

  } else {
    _ftprintf(stderr, TEXT("Committed %lu bytes at address 0x%lp\n"),
              dwPageSize, lpvAddr);
  }

  // Try to lock the committed memory. This fails the first time 
  // because of the guard page.

  bLocked = VirtualLock(lpvAddr, dwPageSize);
  if (!bLocked) {
    _ftprintf(stderr, TEXT("Cannot lock at %lp, error = 0x%lx\n"),
              lpvAddr, GetLastError());
  } else {
    _ftprintf(stderr, TEXT("Lock Achieved at %lp\n"), lpvAddr);
  }

  // Try to lock the committed memory again. This succeeds the second
  // time because the guard page status was removed by the first 
  // access attempt.

  bLocked = VirtualLock(lpvAddr, dwPageSize);

  if (!bLocked) {
    _ftprintf(stderr, TEXT("Cannot get 2nd lock at %lp, error = %lx\n"),
              lpvAddr, GetLastError());
  } else {
    _ftprintf(stderr, TEXT("2nd Lock Achieved at %lp\n"), lpvAddr);
  }

  return 0;
}

La première tentative de verrouillage du bloc de mémoire échoue, soulevant une exception STATUS_GUARD_PAGE_VIOLATION . La deuxième tentative réussit, car la protection de la page de protection du bloc de mémoire a été désactivée par la première tentative.