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
}
}