Concepts de base de l'utilisation des exceptions managées
Cette rubrique décrit la gestion des exceptions dans les applications managées.Autrement dit, une application compilée avec l'option du compilateur pour /clr .
Dans cette rubrique
Lever des exceptions sous /clr
Blocs try/catch pour les extensions du CLR
Remarques
Si vous compilez avec l'option d' /clr , vous pouvez gérer des exceptions CLR ainsi que Gestion des exceptions C++ standard et gestion structurée des exceptions fois SEH ().Une exception CLR est une exception levée par un type managé.La classe de System::Exception fournit plusieurs méthodes utiles pour gérer des exceptions CLR et est recommandée comme classe de base des classes d'exceptions définies par l'utilisateur.
Les types d'exceptions contagieux dérivés d'une interface n'est pas pris en charge sous /clr.En outre, le common langage runtime ne vous permet pas d'intercepter d'exception de dépassement de capacité de la pile ; une exception de dépassement de capacité de la pile met fin au processus.
Pour plus d'informations sur les différences de gestion des exceptions dans les applications managées et non managées, consultez Différences de comportement de gestion des exceptions sous les extensions managées pour C++.
Lever des exceptions sous /clr
L'expression de jet C++ est étendue pour lever un handle vers un type CLR.L'exemple suivant crée un type d'exception personnalisé puis lève une instance de ce type :
// clr_exception_handling.cpp
// compile with: /clr /c
ref struct MyStruct: public System::Exception {
public:
int i;
};
void GlobalFunction() {
MyStruct^ pMyStruct = gcnew MyStruct;
throw pMyStruct;
}
Un type valeur doit être boxed avant d'être levée :
// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
int i;
};
void GlobalFunction() {
MyValueStruct v = {11};
throw (MyValueStruct ^)v;
}
Blocs try/catch pour les extensions du CLR
Mêmes try/structure bloc decatch peut être utilisé pour intercepter le CLR et les exceptions natives :
// clr_exception_handling_3.cpp
// compile with: /clr
using namespace System;
ref struct MyStruct : public Exception {
public:
int i;
};
struct CMyClass {
public:
double d;
};
void GlobalFunction() {
MyStruct^ pMyStruct = gcnew MyStruct;
pMyStruct->i = 11;
throw pMyStruct;
}
void GlobalFunction2() {
CMyClass c = {2.0};
throw c;
}
int main() {
for ( int i = 1; i >= 0; --i ) {
try {
if ( i == 1 )
GlobalFunction2();
if ( i == 0 )
GlobalFunction();
}
catch ( CMyClass& catchC ) {
Console::WriteLine( "In 'catch(CMyClass& catchC)'" );
Console::WriteLine( catchC.d );
}
catch ( MyStruct^ catchException ) {
Console::WriteLine( "In 'catch(MyStruct^ catchException)'" );
Console::WriteLine( catchException->i );
}
}
}
Sortie
In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11
Commande de dérouler pour les objets C++
Dérouler se produit pour tous les objets C++ avec des destructeurs qui peuvent être sur la pile d'exécution entre la fonction se levante et la fonction de gestion.Étant donné que les types CLR sont alloués sur le tas, déroulant ne s'applique pas à eux.
L'ordre des événements pour la levée d'une exception est la suivante :
Le runtime parcourt la pile recherche la clause catch appropriée, ou dans le cas de fois SEH, sauf le filtre correspondant à la fois SEH, pour intercepter l'exception.Les clauses catch se trouvent en premier dans l'ordre lexical, puis dynamiquement à le bas de la pile des appels.
Une fois le gestionnaire approprié est trouvé, la pile est déroulé à ce point.Pour chaque appel de fonction dans la pile, ses objets locaux sont détruits et __finally des blocs sont exécutés, externe le plus imbriqué.
Une fois la pile est déroulée, la clause catch est exécutée.
Types contagieux non managées
Lorsqu'un type d'objet non managé est levée, il est encapsulé avec une exception de type System::Runtime.InteropServices::SEHException.En recherchant la clause catch appropriée, il existe deux possibilités.
Si un type C++ natif est produit, l'exception n'est pas encapsulée et comparée au type produit.Cette comparaison permet un type C++ native à intercepter de manière normale.
Toutefois, si une clause de catch de type SEHException ou de ses classes de base en cours de examen d'abord, la clause arrêtera l'exception.Par conséquent, vous devez placer toutes les clauses catch qui interceptent les types C++ natif d'abord avant que toutes les clauses catch de types CLR.
Prenez note de ce qui suit :
catch(Object^)
et
catch(...)
les deux interrompront tout type levée y compris la fois des exceptions SEH de.
Si un type non managé est interceptée par le Catch (Object^), il ne détruira pas l'objet levé.
En levant ou l'interception des exceptions non managées, nous vous recommandons d'utiliser l'option du compilateur de /EHsc au lieu d' /EHs ou d' /EHa.
Voir aussi
Référence
safe_cast (extensions du composant C++)
Gestion des exceptions dans Visual C++