Sdílet prostřednictvím


Základní koncepce při práci se spravovanými výjimkami

Toto téma popisuje zpracování výjimek ve spravovaných aplikacích. To znamená, že aplikace kompilovaná s možností kompilátoru /clr .

V tomto tématu

Poznámky

Pokud kompilujete pomocí možnosti /clr , můžete zpracovat výjimky CLR i standardní Exception třídu poskytuje mnoho užitečných metod pro zpracování výjimek CLR a doporučuje se jako základní třída pro třídy výjimek definovaných uživatelem.

Zachytávání typů výjimek odvozených z rozhraní není podporováno v / clr. Modul CLR (Common Language Runtime) také neumožňuje zachytit výjimky přetečení zásobníku; Výjimka přetečení zásobníku ukončí proces.

Další informace o rozdílech v zpracování výjimek ve spravovaných a nespravovaných aplikacích najdete v tématu Rozdíly v chování zpracování výjimek v části Spravovaná rozšíření jazyka C++.

Vyvolání výjimek v /clr

Výraz vyvolání jazyka C++ je rozšířen o vyvolání popisovače na typ CLR. Následující příklad vytvoří vlastní typ výjimky a pak vyvolá instanci tohoto typu:

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

Před vyvoláním musí být typ hodnoty v rámečku:

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

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

Try/Catch Blocks for CLR Extensions

Stejnou try/catch strukturu bloku lze použít k zachycení clr i nativních výjimek:

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

Výstup

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

Pořadí odvíjení pro objekty C++

Uvolnění probíhá u všech objektů C++ s destruktory, které mohou být v zásobníku za běhu mezi vyvolání funkce a funkcí zpracování. Vzhledem k tomu, že typy CLR jsou přiděleny na haldě, unwinding se na ně nevztahuje.

Pořadí událostí pro vyvolánou výjimku je následující:

  1. Modul runtime provede zásobník vyhledáním příslušné klauzule catch nebo v případě SEH, s výjimkou filtru pro SEH, aby se výjimka zachytila. Klauzule Catch se prohledávají jako první v lexikálním pořadí a pak dynamicky dolů zásobník volání.

  2. Jakmile se najde správná obslužná rutina, zásobník se v tomto bodě rozbalí. Pro každé volání funkce v zásobníku jsou jeho místní objekty destrukovány a __finally bloky se spouští, od většiny vnořených směrem ven.

  3. Jakmile je zásobník unwound, spustí se klauzule catch.

Zachycení nespravovaných typů

Pokud je vyvolán nespravovaný typ objektu, je zabalen s výjimkou typu SEHException. Při hledání příslušné catch klauzule existují dvě možnosti.

  • Pokud je zjištěn nativní typ jazyka C++, výjimka se rozbalí a porovná se s typem, který byl zjištěn. Toto porovnání umožňuje zachytit nativní typ jazyka C++ normálním způsobem.

  • Pokud catch je však nejprve zkoumána klauzule typu SEHException nebo některé z jejích základních tříd, klauzule zachytí výjimku. Proto byste měli nejprve umístit všechny klauzule catch, které zachytí nativní typy C++, před všechny klauzule catch typů CLR.

Všimněte si, že

catch(Object^)

a

catch(...)

zachytí všechny vyvolané typy včetně výjimek SEH.

Pokud je nespravovaný typ zachycen catch(Object^), nezničí vyvolaný objekt.

Při vyvolání nebo zachytávání nespravovaných výjimek doporučujeme místo /EHs nebo /EHa použít možnost kompilátoru /EHsc.

Viz také

Zpracování výjimek
safe_cast
Zpracování výjimek