Criando páginas de proteção

Uma página de proteção fornece um alarme único para acesso à página de memória. Isso pode ser útil para um aplicativo que precisa monitorar o crescimento de grandes estruturas de dados dinâmicos. Por exemplo, há sistemas operacionais que usam páginas de proteção para implementar a verificação automática de pilha.

Para criar uma página de proteção, defina o modificador de proteção de página PAGE_GUARD para a página. Esse valor pode ser especificado, juntamente com outros modificadores de proteção de página, nas funções VirtualAlloc, VirtualAllocEx, VirtualProtect e VirtualProtectEx . O modificador PAGE_GUARD pode ser usado com qualquer outro modificador de proteção de página, exceto PAGE_NOACCESS.

Se um programa tentar acessar um endereço em uma página de proteção, o sistema gerará uma exceção de STATUS_GUARD_PAGE_VIOLATION (0x80000001). O sistema também limpa o modificador PAGE_GUARD, removendo a página de proteção da página de memória status. O sistema não interromperá a próxima tentativa de acessar a página de memória com uma exceção STATUS_GUARD_PAGE_VIOLATION .

Se ocorrer uma exceção de página de proteção durante um serviço do sistema, o serviço falhará e normalmente retornará alguma falha status indicador. Como o sistema também remove a página de proteção da página de memória relevante status, a próxima invocação do mesmo serviço do sistema não falhará devido a uma exceção de STATUS_GUARD_PAGE_VIOLATION (a menos, é claro, que alguém restabeleça a página de proteção).

O programa curto a seguir ilustra o comportamento da proteção de página de proteção.

/* 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;
}

A primeira tentativa de bloquear o bloco de memória falha, gerando uma exceção STATUS_GUARD_PAGE_VIOLATION . A segunda tentativa é bem-sucedida, pois a proteção de página de proteção do bloco de memória foi desativada pela primeira tentativa.