Utilisation d’un gestionnaire d’exceptions
Les exemples suivants illustrent l’utilisation d’un gestionnaire d’exceptions.
Exemple 1
Le fragment de code suivant utilise la gestion structurée des exceptions pour case activée si une opération de division sur deux entiers 32 bits génère une erreur de division par zéro. Si cela se produit, la fonction retourne FALSE. Sinon, elle retourne 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;
}
Exemple 2
L’exemple de fonction suivant appelle la fonction DebugBreak et utilise la gestion structurée des exceptions pour case activée pour une exception de point d’arrêt. Si l’une d’elles se produit, la fonction retourne FALSE. Sinon, elle retourne TRUE.
L’expression de filtre dans l’exemple utilise la fonction GetExceptionCode pour case activée le type d’exception avant d’exécuter le gestionnaire. Cela permet au système de poursuivre sa recherche d’un gestionnaire approprié si un autre type d’exception se produit.
En outre, l’utilisation de l’instructionreturn dans le bloc de __try d’un gestionnaire d’exceptions diffère de l’utilisation de retour dans le bloc de __try d’un gestionnaire d’arrêt, ce qui entraîne l’arrêt anormal du bloc __try. Il s’agit d’une utilisation valide de l’instruction return dans un gestionnaire d’exceptions.
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;
}
Retournez uniquement EXCEPTION_EXECUTE_HANDLER à partir d’un filtre d’exception lorsque le type d’exception est attendu et que l’adresse d’erreur est connue. Vous devez autoriser le gestionnaire d’exceptions par défaut à traiter les types d’exceptions inattendus et les adresses d’erreur.
Exemple 3
L’exemple suivant montre l’interaction des gestionnaires imbriqués. La fonction RaiseException provoque une exception dans le corps protégé d’un gestionnaire de terminaison qui se trouve à l’intérieur du corps protégé d’un gestionnaire d’exceptions. L’exception entraîne l’évaluation par le système de la fonction FilterFunction, dont la valeur de retour entraîne à son tour l’appel du gestionnaire d’exceptions. Toutefois, avant l’exécution du bloc de gestionnaire d’exceptions, le bloc __finally du gestionnaire d’arrêt est exécuté, car le flux de contrôle a quitté le bloc __try du gestionnaire d’arrêt.
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
}
}