Partager via


Instruction try-except

L’instruction try-except est une extension spécifique à Microsoft qui prend en charge la gestion des exceptions structurées 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++. Elle permet aux applications cibles de garder le contrôle quand des événements se produisent qui mettent normalement fin à l’exécution du programme. Ces événements sont appelés exceptions structurées ou plus brièvement exceptions. Le mécanisme qui traite ces exceptions est appelé gestion des exceptions structurées.

Pour obtenir des informations connexes, consultez Instruction try-finally.

Les exceptions peuvent être basées sur le matériel ou sur le logiciel. La gestion des exceptions structurées est utile même quand les applications ne peuvent pas récupérer complètement d’exceptions matérielles ou logicielles. La gestion des exceptions structurées permet d’afficher les informations des erreurs et d’intercepter l’état interne de l’application pour faciliter le diagnostic du problème. Elle 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++. Cependant, elle n’est pas conçue spécifiquement 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 : les instructions try, catch et throw.

L’instruction composée après la clause __try 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 un ensemble d’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 appelée par la 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érer le contrôle au gestionnaire d’exceptions en exécutant l’instruction composée __except, puis poursuivre l’exécution après le bloc __except.

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.

Passer directement à une instruction __try n’est pas une opération valide, mais quitter une telle instruction est par contre valide. Le gestionnaire d’exceptions n’est pas appelé s’il est mis fin à un processus pendant l’exécution d’une instruction try-except.

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

Le mot clé __leave

Le mot clé __leave est valide seulement dans la section protégée d’une instruction try-except, et son effet est de passer directement à 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 instruction goto permet également de quitter la section protégée, et elle ne dégrade pas les performances comme elle le fait dans une instruction try-finally. La raison en est que le déroulement de la pile ne se produit pas. Cependant, nous vous recommandons d’utiliser le mot clé __leave au lieu d’une instruction goto. La raison en est que vous êtes moins susceptible de faire une erreur de programmation si la section protégée est longue ou complexe.

Fonctions intrinsèques de gestion des exceptions structurées

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

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

La fonction intrinsèque GetExceptionInformation 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 de pointeur PEXCEPTION_RECORD et PCONTEXT sont définis dans le fichier include <winnt.h>, et _EXCEPTION_RECORD et _CONTEXT sont définis dans le fichier include <excpt.h>.

Vous pouvez utiliser GetExceptionCode dans le gestionnaire d’exceptions. Cependant, vous pouvez utiliser GetExceptionInformation seulement dans l’expression du filtre d’exceptions. Les informations vers lesquelles elle pointe sont généralement sur la pile et ne sont plus disponibles quand le contrôle est transféré au gestionnaire d’exceptions.

La fonction intrinsèque AbnormalTermination est disponible dans un gestionnaire de terminaisons. 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 des noms alternatifs pour ces fonctions 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

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