Share via


Écriture d’un filtre d’exception

Vous pouvez gérer une exception en accédant au niveau du gestionnaire d'exceptions ou en reprenant l'exécution. Au lieu d’utiliser le code du gestionnaire d’exceptions pour gérer l’exception et la chute, vous pouvez utiliser une expression de filtre pour propre le problème. Ensuite, en retournant EXCEPTION_CONTINUE_EXECUTION (-1), vous pouvez reprendre le flux normal sans effacer la pile.

Remarque

Certaines exceptions ne peuvent pas être continuées. Si le filtre prend la valeur -1 pour une telle exception, le système déclenche une nouvelle exception. Lorsque vous appelez RaiseException, vous déterminez si l’exception continue.

Par exemple, le code suivant utilise un appel de fonction dans l’expression de filtre : cette fonction gère le problème, puis retourne -1 pour reprendre le flux normal du contrôle :

// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int main() {
   int Eval_Exception( int );

   __try {}

   __except ( Eval_Exception( GetExceptionCode( ))) {
      ;
   }

}
void ResetVars( int ) {}
int Eval_Exception ( int n_except ) {
   if ( n_except != STATUS_INTEGER_OVERFLOW &&
      n_except != STATUS_FLOAT_OVERFLOW )   // Pass on most exceptions
   return EXCEPTION_CONTINUE_SEARCH;

   // Execute some code to clean up problem
   ResetVars( 0 );   // initializes data to 0
   return EXCEPTION_CONTINUE_EXECUTION;
}

Il est judicieux d’utiliser un appel de fonction dans l’expression de filtre chaque fois que le filtre doit effectuer tout ce qui est complexe. L'évaluation de l'expression provoque l'exécution de la fonction, dans ce cas, Eval_Exception.

Notez l’utilisation de GetExceptionCode l’exception pour déterminer l’exception. Cette fonction doit être appelée à l’intérieur de l’expression de filtre de l’instruction __except . Eval_Exception ne peut pas appeler GetExceptionCode, mais il doit avoir le code d’exception passé à celui-ci.

Ce gestionnaire passe le contrôle à un autre gestionnaire sauf si l'exception est un dépassement d'entier ou de virgule flottante. Si tel est le cas, le gestionnaire appelle une fonction (ResetVars n'est qu'un exemple, pas une fonction API) pour réinitialiser des variables globales. Le __except bloc d’instruction, qui dans cet exemple est vide, ne peut jamais être exécuté, car Eval_Exception ne retourne EXCEPTION_EXECUTE_HANDLER jamais (1).

Utilisation d'un appel de fonction est une bonne technique à usage général pour traiter des expressions de filtre complexes. Il y a deux autres fonctionnalités de langage C utiles :

  • l'opérateur conditionnel ;

  • l'opérateur virgule ;

L’opérateur conditionnel est fréquemment utile ici. Il peut être utilisé pour case activée pour un code de retour spécifique, puis retourner l’une des deux valeurs différentes. Par exemple, le filtre dans le code suivant reconnaît l’exception uniquement si l’exception est STATUS_INTEGER_OVERFLOW:

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ? 1 : 0 ) {

Dans ce cas, l'objectif de l'opérateur conditionnel consiste principalement à assurer la clarté, car le code suivant produit les mêmes résultats :

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ) {

L’opérateur conditionnel est plus utile dans les situations où vous souhaiterez peut-être que le filtre soit évalué à -1. EXCEPTION_CONTINUE_EXECUTION

L’opérateur de virgule vous permet d’exécuter plusieurs expressions dans une séquence. Elle retourne ensuite la valeur de la dernière expression. Par exemple, le code suivant enregistre le code d'exception dans une variable puis le teste :

__except( nCode = GetExceptionCode(), nCode == STATUS_INTEGER_OVERFLOW )

Voir aussi

Écriture d’un gestionnaire d’exceptions
Structured Exception Handling (C/C++)