Structured Exception Handling (C/C++)

La gestion structurée des exceptions (SEH) est une extension Microsoft à C et C++ pour gérer certaines situations de code exceptionnelles, telles que les pannes matérielles, correctement. 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++. Il rend votre code plus portable et plus flexible. Toutefois, pour conserver du code existant ou pour des types particuliers de programmes, vous devrez peut-être toujours utiliser SEH.

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 vous assurer que les ressources, telles que les blocs de mémoire et les fichiers, sont libérées correctement si l’exécution se termine de façon inattendue. Vous pouvez également gérer des problèmes spécifiques( par exemple, une mémoire insuffisante) à l’aide d’un code structuré concis qui ne repose pas sur goto des instructions ou des tests élaborés de codes de retour.

Les try-except instructions mentionnées try-finally dans cet article sont des extensions Microsoft aux 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 à l’aide de l’option ou /EHsc de l’option/EHa, les destructeurs pour les objets locaux sont appelés, mais d’autres comportements d’exécution peuvent ne pas être ce que vous attendez. Pour obtenir une illustration, consultez l’exemple plus loin dans cet article. Dans la plupart des cas, au lieu de SEH, nous vous recommandons d’utiliser la gestion des exceptions C++ standard 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 :

  • Gestionnaires d’exceptions, ou __except blocs, qui peuvent répondre ou ignorer l’exception en fonction de la filter-expression valeur. Pour plus d’informations, consultez try-except l’instruction.

  • Gestionnaires de terminaison, ou __finally blocs, qui sont toujours appelés, qu’une exception provoque ou non l’arrêt. Pour plus d’informations, consultez try-finally l’instruction.

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

  • Impossible de reconnaître l’exception et de passer le contrôle à d’autres gestionnaires (EXCEPTION_CONTINUE_SEARCH).

  • Reconnaître l’exception, mais la ignorer (EXCEPTION_CONTINUE_EXECUTION).

  • Reconnaître l’exception et la gérer (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 sur 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éwound. 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 terminaison, vous propre des ressources qui restent ouvertes autrement en raison d’un arrêt anormal. Si vous avez entré une section critique, vous pouvez la quitter dans le gestionnaire d’arrêt. Lorsque le programme va s’arrêter, vous pouvez effectuer d’autres tâches de ménage telles que la fermeture et la suppression de fichiers temporaires.

Étapes suivantes

Exemple

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

#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 CPPEX de contrôle de test local n’est pas définie, le TestClass destructeur 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 CPPEX qu’il est défini à l’aide /DCPPEX (afin qu’une exception C++ soit levée), le TestClass destructeur 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 TestClass destructeur exécute si une exception a été levée à l’aide d’une expression C++ throw standard ou à l’aide de SEH. Autrement dit, si CPPEX elle est définie 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>
Erreurs et gestion des exceptions
Gestion des exceptions structurées (Windows)