Uso de un controlador de excepciones
En los ejemplos siguientes se muestra el uso de un controlador de excepciones.
Ejemplo 1
El fragmento de código siguiente usa el control de excepciones estructurado para comprobar si una operación de división en dos enteros de 32 bits producirá un error de división por cero. Si esto ocurre, la función devuelve FALSE; de lo contrario, devuelve 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;
}
Ejemplo 2
La siguiente función de ejemplo llama a la función DebugBreak y usa el control de excepciones estructurado para comprobar si hay una excepción de punto de interrupción. Si se produce, la función devuelve FALSE; de lo contrario, devuelve TRUE.
La expresión de filtro del ejemplo usa la función GetExceptionCode para comprobar el tipo de excepción antes de ejecutar el controlador. Esto permite al sistema continuar su búsqueda de un controlador adecuado si se produce algún otro tipo de excepción.
Además, el uso de la instrucción return en el bloque __try de un controlador de excepciones difiere del uso de return en el bloque __try de un controlador de terminación, lo que provoca una terminación anómala del bloque de __try . Se trata de un uso válido de la instrucción return en un controlador de excepciones.
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;
}
Solo devuelve EXCEPTION_EXECUTE_HANDLER de un filtro de excepción cuando se espera el tipo de excepción y se conoce la dirección de error. Debe permitir que el controlador de excepciones predeterminado procese tipos de excepción inesperados y direcciones de error.
Ejemplo 3
En el ejemplo siguiente se muestra la interacción de los controladores anidados. La función RaiseException provoca una excepción en el cuerpo protegido de un controlador de terminación que se encuentra dentro del cuerpo protegido de un controlador de excepciones. La excepción hace que el sistema evalúe la función FilterFunction, cuyo valor devuelto a su vez hace que se invoque el controlador de excepciones. Sin embargo, antes de ejecutar el bloque del controlador de excepciones, se ejecuta el bloque __finally del controlador de terminación porque el flujo de control ha dejado el bloque __try del controlador de terminación.
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
}
}