Usando um manipulador de exceção

Os exemplos a seguir demonstram o uso de um manipulador de exceções.

Exemplo 1

O fragmento de código a seguir usa manipulação de exceção estruturada para verificar se uma operação de divisão em dois inteiros de 32 bits resultará em um erro de divisão por zero. Se isso ocorrer, a função retornará FALSE— caso contrário, ela retornará TRUE.

BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
    __try 
    { 
        *pResult = dividend / divisor; 
    } 
    __except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ? 
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    { 
        return FALSE;
    }
    return TRUE;
} 

Exemplo 2

A função de exemplo a seguir chama a função DebugBreak e usa o tratamento de exceção estruturado para verificar se há uma exceção de ponto de interrupção. Se ocorrer um, a função retornará FALSE— caso contrário, retornará TRUE.

A expressão de filtro no exemplo usa a função GetExceptionCode para verificar o tipo de exceção antes de executar o manipulador. Isso permite que o sistema continue sua busca por um manipulador apropriado se algum outro tipo de exceção ocorrer.

Além disso, o uso da instrução return no bloco __try de um manipulador de exceção difere do uso de return no bloco __try de um manipulador de terminação, o que causa um encerramento anormal do bloco __try. Esse é um uso válido da instrução return em um manipulador de exceções.

BOOL CheckForDebugger()
{
    __try 
    {
        DebugBreak();
    }
    __except(GetExceptionCode() == EXCEPTION_BREAKPOINT ? 
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
    {
        // No debugger is attached, so return FALSE 
        // and continue.
        return FALSE;
    }
    return TRUE;
}

Só retorne EXCEPTION_EXECUTE_HANDLER de um filtro de exceção quando o tipo de exceção for esperado e o endereço com falha for conhecido. Você deve permitir que o manipulador de exceções padrão processe tipos de exceção inesperados e endereços com falha.

Exemplo 3

O exemplo a seguir mostra a interação de manipuladores aninhados. A função RaiseException causa uma exceção no corpo protegido de um manipulador de terminação que está dentro do corpo protegido de um manipulador de exceção. A exceção faz com que o sistema avalie a função FilterFunction, cujo valor de retorno, por sua vez, faz com que o manipulador de exceção seja chamado. No entanto, antes que o bloco do manipulador de exceção seja executado, o bloco __finally do manipulador de terminação é executado porque o fluxo de controle deixou o bloco __try do manipulador de terminação.

DWORD FilterFunction() 
{ 
    printf("1 ");                     // printed first 
    return EXCEPTION_EXECUTE_HANDLER; 
} 
 
VOID main(VOID) 
{ 
    __try 
    { 
        __try 
        { 
            RaiseException( 
                1,                    // exception code 
                0,                    // continuable exception 
                0, NULL);             // no arguments 
        } 
        __finally 
        { 
            printf("2 ");             // this is printed second 
        } 
    } 
    __except ( FilterFunction() ) 
    { 
        printf("3\n");                // this is printed last 
    } 
}