Partager via


Structured Exception Handling (C/C++)

Gestion structurée des exceptions (SEH) est une extension Microsoft à C et C++ pour gérer avec panache certaines situations de code exceptionnelles, telles que les pannes matérielles. Bien que Windows et Microsoft C++ prennent en charge SEH, nous vous recommandons d’utiliser la gestion des exceptions C++ standard ISO dans le code C++. Cela rend votre code plus portable et plus flexible. Néanmoins, vous devrez peut-être encore utiliser SEH pour maintenir le code existant ou pour des types particuliers de programmes.

Section spécifique à Microsoft :

Grammaire

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

try-finally-statement :
__try compound-statement __finally compound-statement

Notes

Avec SEH, vous pouvez garantir que les ressources telles que les blocs de mémoire et les fichiers seront publiées si l’exécution se termine de manière inattendue. Vous pouvez également gérer des problèmes spécifiques (par exemple, une mémoire insuffisante) en utilisant un code structuré concis qui ne repose pas sur les instructions goto ni sur des tests élaborés de codes de retour.

Les instructions try-except et try-finally référencées dans cet article sont des extensions Microsoft des langages C et C++. Elles prennent en charge SEH en permettant aux applications de prendre le contrôle d'un programme après des événements qui termineraient sinon son exécution. Bien que la gestion SEH fonctionne avec des fichiers sources C++, elle n'est pas spécifiquement conçue pour C++. Si vous utilisez SEH dans un programme C++ que vous compilez en utilisant l’option /EHa ou /EHsc, des destructeurs d’objets locaux sont appelés, mais d’autres comportements d’exécution non prévus peuvent apparaître. Pour obtenir une illustration, consultez l’exemple présenté plus loin dans cet article. Dans la plupart des cas, au lieu de SEH, nous vous recommandons d’utiliser la gestion des exceptions C++ conforme à la norme ISO. En utilisant la gestion des exceptions C++, vous pouvez garantir que votre code est plus portable et gérer les exceptions de tout type.

Si vous avez du code C qui utilise SEH, vous pouvez le combiner avec du code C++ qui utilise la gestion des exceptions C++. Pour plus d’informations, consultez Gérer les exceptions structurées en C++.

Il existe deux mécanismes de gestion SEH :

Ces deux types de gestionnaires sont distincts, mais étroitement liés via un processus appelé déroulement de la pile. Quand une exception structurée se produit, Windows cherche le gestionnaire d’exceptions le plus récemment installé qui est actif. Le gestionnaire peut effectuer l'une des trois opérations suivantes :

  • Il ne reconnaît pas l’exception et passe le contrôle à d’autres gestionnaires (EXCEPTION_CONTINUE_SEARCH).

  • Il reconnaît l’exception, mais la fait disparaître (EXCEPTION_CONTINUE_EXECUTION).

  • Il reconnaît l’exception et la gère (EXCEPTION_EXECUTE_HANDLER).

Le gestionnaire d'exceptions qui reconnaît l'exception peut ne pas être dans la fonction qui s'exécutait quand l'exception s'est produite. Il peut s’agir d’une fonction beaucoup plus élevée dans la pile. La fonction en cours d'exécution et toutes les autres fonctions sur le frame de pile sont terminées. Pendant ce processus, la pile est déroulée. Autrement dit, les variables locales non statiques des fonctions terminées sont effacées de la pile.

Tout en déroulant la pile, le système d'exploitation appelle tous les gestionnaires de terminaisons que vous avez écrits pour chaque fonction. En utilisant un gestionnaire de terminaisons, vous pouvez nettoyer les ressources qui autrement resteraient ouvertes en raison d’un achèvement anormal. Si vous entrez dans une section critique, vous pouvez la quitter via le gestionnaire de terminaisons. Lorsque le programme est en cours d’arrêt, vous pouvez effectuer d’autres tâches de gestion interne telles que la fermeture et la suppression des fichiers temporaires.

Étapes suivantes

Exemple

Comme indiqué précédemment, les destructeurs d’objets locaux sont appelés si vous utilisez SEH dans un programme C++ et que vous le compilez en utilisant l’option /EHa ou /EHsc. Toutefois, le comportement pendant l’exécution peut ne pas être celui prévu si vous utilisez également des exceptions C++. Cet exemple illustre ces différences de comportement.

#include <stdio.h>
#include <Windows.h>
#include <exception>

class TestClass
{
public:
    ~TestClass()
    {
        printf("Destroying TestClass!\n");
    }
};

__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf("Throwing C++ exception\n");
    throw std::exception("");
#else
    printf("Triggering SEH exception\n");
    volatile int *pInt = 0x00000000;
    *pInt = 20;
#endif
}

__declspec(noinline) void TestExceptions()
{
    TestClass d;
    TestCPPEX();
}

int main()
{
    __try
    {
        TestExceptions();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf("Executing SEH __except block\n");
    }

    return 0;
}

Si vous utilisez /EHsc pour compiler ce code, mais que la macro de contrôle de test local CPPEX n’est pas définie, le destructeur TestClass ne s’exécute pas. Une sortie classique ressemble à ceci :

Triggering SEH exception
Executing SEH __except block

Si vous utilisez /EHsc pour compiler le code et que CPPEX est défini à l’aide de /DCPPEX (afin qu’une exception C++ soit levée), le destructeur de TestClass s’exécute et la sortie ressemble à ceci :

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Si vous utilisez /EHa pour compiler le code, le destructeur TestClass s’exécute si une exception a été levée à l’aide d’une expression throw C++ standard ou à l’aide de SEH. Autrement dit, si CPPEX est défini ou non. Une sortie classique ressemble à ceci :

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Pour plus d’informations, consultez /EH (Modèle de gestion des exceptions).

FIN de la section spécifique à Microsoft

Voir aussi

Traitement des exceptions
Mots clés
<exception>
Gestion des erreurs et des exceptions
Gestion structurée des exceptions (Windows)