Megosztás:


A felügyelt kivételek használatának alapfogalmai

Ez a témakör a felügyelt alkalmazások kivételkezelését ismerteti. Ez egy olyan alkalmazás, amely a /clr fordító beállítással van lefordítva.

Ebben a témakörben

Megjegyzések

Ha a /clr beállítással fordít, kezelheti a CLR-kivételeket, valamint a standard Exception osztály számos hasznos módszert kínál a CLR-kivételek feldolgozásához, és a felhasználó által definiált kivételosztályok alaposztályaként ajánlott.

Az interfészből eredő kivétel típusok nem támogatottak /clr alatt. Emellett a közös nyelvi futtatókörnyezet nem teszi lehetővé a verem túlcsordulási kivételek kezelését; egy verem túlcsordulási kivétel leállítja a folyamatot.

A felügyelt és a nem felügyelt alkalmazások kivételkezelésének különbségeiről további információt a C++ felügyelt bővítmények kivételkezelési viselkedésének eltérései című témakörben talál.

Kivételek kivetése a /clr területen

A C++ dobási kifejezés ki van terjesztve, hogy egy referenciát dobjon egy CLR-típusra. Az alábbi példa létrehoz egy egyéni kivételtípust, majd létrehoz egy ilyen típusú példányt:

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

A dobás előtt be kell jelölni egy értéktípust:

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

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

A CLR-bővítmények kipróbálási/fogási blokkjai

Ugyanez a try/catch blokkstruktúra használható a CLR és a natív kivételek elfogására is:

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

Kimenet

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

A C++ objektumok visszatekerésének sorrendje

A visszatekerés minden olyan C++ objektum esetében történik, amelynek destruktorai a dobási függvény és a kezelési függvény közötti futásidejű veremen lehetnek. Mivel a CLR-típusok a halomra vannak lefoglalva, a visszatekerés nem vonatkozik rájuk.

A kivétel kiváltásának eseménysorrendje a következő:

  1. A futtatókörnyezet végiglépked a veremen, hogy megkeresse a megfelelő kivételkezelő záradékot, vagy SEH esetében az SEH kivételek szűrőjét, amely elkapja a kivételt. A catch záradékok keresésére először lexikális sorrendben kerül sor, majd dinamikusan lefelé a hívásveremen.

  2. Miután megtalálta a megfelelő kezelőt, a verem erre a pontra lesz feloldva. Minden függvényhívásnál a veremben a helyi objektumokat megsemmisítik, és a __finally blokkokat hajtják végre, a legbelsőbbtől kifelé.

  3. A verem feloldása után a rendszer végrehajtja a fogási záradékot.

Nem felügyelt típusok elfogása

Ha egy nem felügyelt objektumtípust dobnak ki, a rendszer a típus SEHExceptionkivételével burkolja azt. A megfelelő catch záradék keresésekor két lehetőség áll rendelkezésre.

  • Natív C++-típus esetén a kivétel fel van bontva, és összehasonlítva az észlelt típussal. Ez az összehasonlítás lehetővé teszi, hogy a natív C++ típus a szokásos módon legyen kezelve.

  • Ha azonban először egy catchSEHException típusú záradékot vagy annak valamelyik alaposztályát vizsgálja meg, a záradék elfogja a kivételt. Ezért minden olyan fogási záradékot, amely a natív C++ típusokat fogja el, a CLR-típusok fogási záradékai elé kell elhelyezni.

Vegye figyelembe, hogy

catch(Object^)

és

catch(...)

a rendszer mindkét esetben észleli a dobott típusokat, beleértve az SEH-kivételeket is.

Ha a catch(Object^) nem felügyelt típust kap, az nem fogja megsemmisíteni a kidobott objektumot.

Ha kezeletlen kivételeket dob vagy kezel, javasoljuk, hogy az /EHsc fordítói opciót használja a /EHs vagy /EHa helyett.

Lásd még

Kivételkezelés
safe_cast
Kivételkezelés