Freigeben über


Grundlegende Konzepte zur Verwendung verwalteter Ausnahmen

In diesem Thema wird die Ausnahmebehandlung in verwalteten Anwendungen erläutert. Das heißt, eine Anwendung, die mit der Compileroption /clr kompiliert wird.

In diesem Thema

Hinweise

Wenn Sie mit der Option "/clr " kompilieren, können Sie CLR-Ausnahmen behandeln sowie standardklasse Exception viele nützliche Methoden zum Verarbeiten von CLR-Ausnahmen bereitstellen und wird als Basisklasse für benutzerdefinierte Ausnahmeklassen empfohlen.

Das Abfangen von Ausnahmetypen, die von einer Schnittstelle abgeleitet sind, wird unter "/clr" nicht unterstützt. Außerdem ermöglicht ihnen die Common Language Runtime nicht das Abfangen von Stapelüberlaufausnahmen; Eine Stapelüberlaufausnahme beendet den Prozess.

Weitere Informationen zu Unterschieden bei der Ausnahmebehandlung in verwalteten und nicht verwalteten Anwendungen finden Sie unter "Unterschiede beim Verhalten der Ausnahmebehandlung unter verwalteten Erweiterungen für C++".

Auslösen von Ausnahmen unter /clr

Der C++-throw-Ausdruck wird erweitert, um ein Handle auf einen CLR-Typ zu werfen. Im folgenden Beispiel wird ein benutzerdefinierter Ausnahmetyp erstellt und anschließend eine Instanz dieses Typs ausgelöst:

// 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;
}

Vor dem Auslösen muss ein Werttyp geboxed werden:

// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
   int i;
};

void GlobalFunction() {
   MyValueStruct v = {11};
   throw (MyValueStruct ^)v;
}

Try/Catch-Blöcke für CLR-Erweiterungen

Die gleiche try/catch Blockstruktur kann zum Abfangen von CLR- und systemeigenen Ausnahmen verwendet werden:

// 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 );
      }
   }
}

Output

In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11

Reihenfolge des Entpackens für C++-Objekte

Die Rückabwicklung erfolgt für alle C++-Objekte mit Destruktoren, die sich im Laufzeitstapel zwischen der werfenden Funktion und der auffangenden Funktion befinden können. Da CLR-Typen auf dem Heap zugeordnet sind, gilt das Entspannen nicht für sie.

Die Reihenfolge der Ereignisse für eine ausgelöste Ausnahme lautet wie folgt:

  1. Die Laufzeitumgebung durchläuft den Stapel auf der Suche nach der entsprechenden Catch-Klausel oder, im Fall von SEH, einem Ausnahmefilter für SEH, um die Ausnahme abzufangen. Catch-Klauseln werden zuerst in lexikalischer Reihenfolge und dann dynamisch nach unten im Aufrufstapel durchsucht.

  2. Sobald der richtige Handler gefunden wurde, wird der Stapel an diesem Punkt entladen. Für jeden Funktionsaufruf im Stapel werden die lokalen Objekte aufgelöst, und die __finally-Blöcke werden vom innersten bis zum äußersten ausgeführt.

  3. Sobald der Stapel entwundt ist, wird die Catch-Klausel ausgeführt.

Abfangen nicht verwalteter Typen

Wenn ein nicht verwalteter Objekttyp ausgelöst wird, wird er mit ausnahme des Typs SEHExceptionumschlossen. Bei der Suche nach der entsprechenden catch Klausel gibt es zwei Möglichkeiten.

  • Wenn ein systemeigener C++-Typ gefunden wird, wird die Ausnahme entpackt und mit dem gefundenen Typ verglichen. Mit diesem Vergleich kann ein systemeigener C++-Typ normal abgefangen werden.

  • Wenn jedoch eine catch Klausel vom Typ SEHException oder eine seiner Basisklassen zuerst untersucht wird, wird die Ausnahme von der Klausel abgefangen. Daher sollten Sie zuerst alle Catch-Klauseln platzieren, die systemeigene C++-Typen abfangen, vor Catch-Klauseln von CLR-Typen.

Beachten Sie, dass

catch(Object^)

und

catch(...)

Beide fangen alle ausgelösten Typen, einschließlich SEH-Ausnahmen, ab.

Wenn ein nicht verwalteter Typ von catch(Object^) abgefangen wird, wird das ausgelöste Objekt nicht zerstört.

Beim Auslösen oder Abfangen nicht verwalteter Ausnahmen wird empfohlen, die /EHsc-Compileroption anstelle von /EHs oder /EHa zu verwenden.

Siehe auch

Ausnahmebehandlung
safe_cast
Ausnahmebehandlung