Instruction try-except

L’instruction try-except est une extension spécifique à Microsoft qui prend en charge la gestion structurée des exceptions dans les langages C et C++.

    // . . .
    __try {
        // guarded code
    }
    __except ( /* filter expression */ ) {
        // termination code
    }
    // . . .

Grammaire

try-except-statement:
__try compound-statement __except ( expression ) compound-statement

Notes

L’instruction try-except est une extension Microsoft aux langages C et C++. Il permet aux applications cibles de contrôler quand des événements se produisent qui terminent normalement l’exécution du programme. Ces événements sont appelés exceptions structurées ou exceptions pour un court terme. Le mécanisme qui traite de ces exceptions est appelé gestion des exceptions structurées (SEH).

Pour plus d’informations, consultez l’instruction try-finally.

Les exceptions peuvent être basées sur du matériel ou logicielles. La gestion structurée des exceptions est utile même si les applications ne peuvent pas récupérer complètement à partir d’exceptions matérielles ou logicielles. SEH permet d’afficher des informations d’erreur et d’intercepter l’état interne de l’application pour aider à diagnostiquer le problème. Il est particulièrement utile pour les problèmes intermittents qui ne sont pas faciles à reproduire.

Remarque

La gestion structurée des exceptions fonctionne avec Win32 pour les fichiers sources C et C++. Toutefois, il n’est pas spécifiquement conçu pour C++. Vous pouvez vous assurer que votre code est plus portable en utilisant la gestion des exceptions C++. En outre, la gestion des exceptions C++ est plus souple, car elle permet de traiter des exceptions de tout type. Pour les programmes C++, nous vous recommandons d’utiliser la gestion des exceptions C++ native : try, catch et throw instructions.

L’instruction composée après la __try clause est le corps ou la section protégée. L’expression __except est également appelée expression de filtre . Sa valeur détermine la façon dont l’exception est gérée. L'instruction composée après la clause __except constitue le gestionnaire d'exceptions. Le gestionnaire spécifie les actions à effectuer si une exception est levée pendant l’exécution de la section du corps. L'exécution se déroule comme suit :

  1. La section protégée est exécutée.

  2. Si aucune exception ne se produit pendant l'exécution de la section protégée, l'exécution se poursuit à l'instruction située après la clause __except.

  3. Si une exception se produit pendant l’exécution de la section protégée ou dans une routine les appels de section protégée, l’expression __except est évaluée. Il existe trois valeurs possibles :

    • EXCEPTION_CONTINUE_EXECUTION (-1) L’exception est ignorée. Poursuivre l'exécution au point où l'exception s'est produite.

    • EXCEPTION_CONTINUE_SEARCH (0) L’exception n’est pas reconnue. Poursuivre la recherche d’un gestionnaire dans la pile, en premier pour qu’il contienne des instructions try-except, puis pour les gestionnaires avec la priorité la plus élevée suivante.

    • EXCEPTION_EXECUTE_HANDLER (1) L’exception est reconnue. Transférez le contrôle vers le gestionnaire d’exceptions en exécutant l’instruction __except composée, puis continuez l’exécution après le __except bloc.

L’expression __except est évaluée en tant qu’expression C. Elle est limitée à une seule valeur, à l’opérateur d’expression conditionnelle ou à l’opérateur de virgule. Si un traitement plus étendu est requis, l'expression peut appeler une routine qui retourne l'une des trois valeurs répertoriées ci-dessus.

Chaque application peut avoir son propre gestionnaire d'exceptions.

Il n’est pas valide de sauter dans une __try instruction, mais valide pour sortir d’un. Le gestionnaire d’exceptions n’est pas appelé si un processus est arrêté au milieu de l’exécution d’une try-except instruction.

Pour la compatibilité avec les versions précédentes, _try, _except et _leave sont des synonymes pour __try, __exceptet __leave sauf si l’option du compilateur /Za (Désactiver les extensions de langage) est spécifiée.

Le mot clé __leave

Le __leave mot clé est valide uniquement dans la section protégée d’une try-except instruction, et son effet est de passer à la fin de la section protégée. L'exécution se poursuit à la première instruction située après le gestionnaire d'exceptions.

Une goto instruction peut également sortir de la section protégée et ne dégrade pas les performances comme dans une instruction try-finally . Cela est dû au fait que le déroulement de la pile ne se produit pas. Toutefois, nous vous recommandons d’utiliser la __leave mot clé plutôt qu’une goto instruction. La raison est que vous êtes moins susceptible de faire une erreur de programmation si la section protégée est volumineuse ou complexe.

Fonctions intrinsèques de gestion des exceptions structurées

La gestion structurée des exceptions fournit deux fonctions intrinsèques qui sont disponibles pour être utilisées avec l’instruction try-except : GetExceptionCode et GetExceptionInformation.

GetExceptionCode retourne le code (entier 32 bits) de l’exception.

La fonction GetExceptionInformation intrinsèque retourne un pointeur vers une structure EXCEPTION_POINTERS contenant des informations supplémentaires sur l’exception. Ce pointeur vous permet d'accéder à l'état de l'ordinateur qui existait au moment d'une exception matérielle. La structure est comme suit :

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

Les types PEXCEPTION_RECORD de pointeur et PCONTEXT sont définis dans le fichier <include winnt.h> et _CONTEXT_EXCEPTION_RECORD sont définis dans le fichier <include excpt.h>

Vous pouvez utiliser GetExceptionCode dans le gestionnaire d’exceptions. Toutefois, vous ne pouvez utiliser GetExceptionInformation que dans l’expression de filtre d’exception. Les informations qu’il pointe vers sont généralement sur la pile et ne sont plus disponibles lorsque le contrôle est transféré vers le gestionnaire d’exceptions.

La fonction intrinsèque AbnormalTermination est disponible dans un gestionnaire d’arrêt. Elle retourne 0 si le corps de l’instruction try-finally se termine séquentiellement. Dans tous les autres cas, elle retourne 1.

<excpt.h> définit certains autres noms pour ces intrinsèques :

GetExceptionCode équivaut à _exception_code

GetExceptionInformation équivaut à _exception_info

AbnormalTermination équivaut à _abnormal_termination

Exemple

// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
    puts("in filter.");
    if (code == EXCEPTION_ACCESS_VIOLATION)
    {
        puts("caught AV as expected.");
        return EXCEPTION_EXECUTE_HANDLER;
    }
    else
    {
        puts("didn't catch AV, unexpected.");
        return EXCEPTION_CONTINUE_SEARCH;
    };
}

int main()
{
    int* p = 0x00000000;   // pointer to NULL
    puts("hello");
    __try
    {
        puts("in try");
        __try
        {
            puts("in try");
            *p = 13;    // causes an access violation exception;
        }
        __finally
        {
            puts("in finally. termination: ");
            puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
        }
    }
    __except(filter(GetExceptionCode(), GetExceptionInformation()))
    {
        puts("in except");
    }
    puts("world");
}

Sortie

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

Voir aussi

Écriture d’un gestionnaire d’exceptions
Structured Exception Handling (C/C++)
Mots clés