Tratando exceções

O sistema operacional usa a manipulação de exceção estruturada para sinalizar determinados tipos de erros. Uma rotina chamada por um driver pode criar uma exceção que o driver deve manipular.

O sistema intercepta os seguintes tipos gerais de exceções:

  1. Falhas ou interceptações definidas por hardware, como,

    • Violações de acesso (veja abaixo)
    • Desalinhamentos de tipo de dados (como uma entidade de 16 bits alinhada em um limite de byte ímpar)
    • Instruções ilícitas e privilegiadas
    • Sequências de bloqueio inválidas (tentando executar uma sequência inválida de instruções dentro de uma seção de código intertravada)
    • Inteiro divide por zero e estouros
    • O ponto flutuante divide por zero, estouros, subfluxos e operadores reservados
    • Pontos de interrupção e execução de etapa única (para dar suporte a depurdores)
  2. Exceções definidas pelo software do sistema, como,

    • Violações de página de proteção (tentando carregar ou armazenar dados de ou para um local dentro de uma página de proteção)
    • Erros de leitura de página (tentando ler uma página na memória e encontrando um erro de E/S simultânea)

Uma violação de acesso é uma tentativa de executar uma operação em uma página que não é permitida nas configurações de proteção de página atuais. As violações de acesso ocorrem nas seguintes situações:

  • Uma operação de leitura ou gravação inválida, como gravar em uma página somente leitura.

  • Para acessar a memória além do limite do espaço de endereço do programa atual (conhecido como violação de comprimento).

  • Para acessar uma página atualmente residente, mas dedicada ao uso de um componente do sistema. Por exemplo, o código de modo de usuário não tem permissão para acessar uma página que o kernel está usando.

Se uma operação pode causar uma exceção, o driver deve colocar a operação em um bloco try/except . Acessos de locais no modo de usuário são causas típicas de exceções. Por exemplo, a rotina ProbeForWrite verifica se o driver pode realmente gravar em um buffer de modo de usuário. Se não for possível, a rotina gera uma STATUS_ACCESS_VIOLATION exceção. No exemplo de código a seguir, o driver chama ProbeForWrite em um try/except para que ele possa lidar com a exceção resultante, se ocorrer.

try {
    ...
    ProbeForWrite(Buffer, BufferSize, BufferAlignment);
 
    /* Note that any access (not just the probe, which must come first,
     * by the way) to Buffer must also be within a try-except.
     */
    ...
} except (EXCEPTION_EXECUTE_HANDLER) {
    /* Error handling code */
    ...
}

Os drivers devem tratar todas as exceções ativas. Uma exceção que não é tratada faz com que o sistema verifique os bugs. O driver que faz com que a exceção seja a elecada deve lidar com ela: um driver de nível inferior não pode depender de um driver de nível superior para lidar com a exceção.

Os drivers podem criar uma exceção diretamente usando as rotinas ExRaiseAccessViolation, ExRaiseDatatypeMisalignment ou ExRaiseStatus . O driver deve lidar com quaisquer exceções que essas rotinas aumentem.

Veja a seguir uma lista parcial de rotinas que, pelo menos em determinadas situações, podem criar uma exceção:

Acessos de memória a buffers de modo de usuário também podem causar violações de acesso. Para obter mais informações, consulte Erros em Referenciar User-Space endereços.

Observe que o tratamento de exceção estruturado é diferente das exceções do C++. O kernel não dá suporte a exceções C++.

Para obter mais informações sobre o tratamento de exceção estruturado, consulte o SDK do Microsoft Windows e a documentação Visual Studio dados.