Filtrage des exceptions structurées (C++)

De RAD Studio
Aller à : navigation, rechercher

Remonter à Exceptions structurées sous Win32 (C++)

Une expression de filtrage peut invoquer une fonction de filtrage, mais la fonction de filtrage ne peut pas appeler GetExceptionInformation. Vous pouvez passer la valeur de retour de GetExceptionInformation, en tant que paramètre, à une fonction de filtrage.

Pour passer les informations EXCEPTION_POINTERS à un gestionnaire d'exceptions, l'expression de filtrage ou la fonction de filtrage doit copier le pointeur ou les données de GetExceptionInformation à un emplacement où le gestionnaire peut y accéder par la suite.

Dans le cas d'instructions try-except imbriquées, l'expression de filtrage de chaque instruction est évaluée jusqu'à ce que EXCEPTION_EXECUTE_HANDLER ou EXCEPTION_CONTINUE_EXECUTION soit trouvé. Une expression de filtrage peut invoquer GetExceptionInformation pour obtenir des informations d'exception.

Tant que GetExceptionInformation ou GetExceptionCode est appelée directement dans l'expression fournie à __except, vous pouvez utiliser une fonction pour déterminer comment traiter l'exception plutôt que d'essayer de créer une expression C++ complexe. Presque toutes les informations nécessaires à la gestion d'une exception peuvent être extraites du résultat de GetExceptionInformation. GetExceptionInformation renvoie un pointeur sur une structure EXCEPTION_POINTERS :

 
 struct EXCEPTION_POINTERS {
 	EXCEPTION_RECORD *ExceptionRecord;
 	CONTEXT *Context;
 };

EXCEPTION_RECORD contient l'état indépendant de la machine :

 struct EXCEPTION_RECORD {
 	DWORD ExceptionCode;
 	DWORD ExceptionFlags;
 	struct EXCEPTION_RECORD *ExceptionRecord;
 	void *ExceptionAddress;
 	DWORD NumberParameters;
 	DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
 };

Typiquement, la fonction de filtrage consulte les informations du ExceptionRecord pour décider de la réponse. Des informations plus spécifiques sont parfois nécessaires (en particulier, si l'action à prendre est EXCEPTION_CONTINUE_EXECUTION : si rien n'est fait, le code ayant causé l'exception pourrait être exécuté à nouveau). Pour cette situation, l'autre champ de la structure EXCEPTION_POINTERS fournit l'état du processeur au moment de l'exception. Si cette structure est modifiée et que le filtre renvoie EXCEPTION_CONTINUE_EXCEPTION, il est utilisé pour définir l'état du thread avant de poursuivre l'exécution. Par exemple :

static int xfilter(EXCEPTION_POINTERS *xp) {
 int rc;
 EXCEPTION_RECORD *xr = xp->ExceptionRecord;
 CONTEXT *xc = xp->Context;
 switch (xr->ExceptionCode) {
 case EXCEPTION_BREAKPOINT:
 		// whoops, someone left an embedded breakpoint.
 		// just step over it (1 byte on x86)
 		++xc->Eip;
 	rc = EXCEPTION_CONTINUE_EXECUTION;
 	break;
 case EXCEPTION_ACCESS_VIOLATION:
 	rc = EXCEPTION_EXECUTE_HANDLER;
 	break;
 default:
 		// give up
 		rc = EXCEPTION_CONTINUE_SEARCH;
 	break;
 };
 return rc;
 }
 
 // ...
 
 EXCEPTION_POINTERS * xp;
 
 try {
 func();
 }
 __except (xfilter(xp = GetExceptionInformation())) {
 abort();
 }

Voir aussi