Tratando exceções

O sistema operacional usa o tratamento de exceção estruturado para sinalizar determinados tipos de erros. Uma rotina chamada por um driver pode gerar uma exceção que o driver deve manipular.

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

  1. Falhas ou armadilhas definidas por hardware, como,

    • Violações de acesso (veja abaixo)
    • Desalinhamentos do tipo de dados (como uma entidade de 16 bits alinhada em um limite de bytes ímpares)
    • Instruções ilegais e privilegiadas
    • Sequências de bloqueio inválidas (tentando executar uma sequência inválida de instruções em uma seção intertravada de código)
    • O inteiro é dividido por zero e transborda
    • Divisões de ponto flutuante por zero, estouros, fluxos inferiores e operandos reservados
    • Pontos de interrupção e execução de etapa única (para dar suporte a depuradores)
  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âneo)

Uma violação de acesso é uma tentativa de executar uma operação em uma página que não é permitida nas configurações atuais de proteção de página. 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 que atualmente é residente, mas dedicada ao uso de um componente do sistema. Por exemplo, o código do 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 deverá colocar a operação em um bloco try/except . Os 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 puder, a rotina gerará uma exceção STATUS_ACCESS_VIOLATION. No exemplo de código a seguir, o driver chama ProbeForWrite em uma tentativa/exceto para que ele possa lidar com a exceção resultante, se uma 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 lidar com quaisquer exceções geradas. Uma exceção que não é tratada faz com que o sistema bug marcar. O driver que faz com que a exceção seja gerada deve lidar com isso: um driver de nível inferior não pode contar com um driver de nível superior para lidar com a exceção.

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

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

Os 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 Referência a endereços User-Space.

Observe que a manipulação de exceção estruturada é distinta 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ções estruturadas, consulte o SDK do Microsoft Windows e a documentação do Visual Studio.