Partilhar via


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, existem sistemas operativos 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, no VirtualAlloc, VirtualAllocEx, VirtualProtecte funções de 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 dentro de uma página de proteção, o sistema gerará uma exceção STATUS_GUARD_PAGE_VIOLATION (0x80000001). O sistema também limpa o modificador de PAGE_GUARD, removendo o status de proteção da página de memória. O sistema não irá impedir a próxima tentativa de aceder à 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á algum indicador de status de falha. Como o sistema também remove o status de página de proteção da página de memória relevante, a próxima invocação do mesmo serviço do sistema não falhará devido a uma exceção 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 guarda.

/* 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 STATUS_GUARD_PAGE_VIOLATION exceção. A segunda tentativa tem sucesso, porque a proteção da página de guarda do bloco de memória foi desativada pela primeira tentativa.