Dela via


Grundläggande begrepp i att använda hanterade undantag

I det här avsnittet beskrivs undantagshantering i hanterade program. Det vill: ett program som kompileras med kompilatoralternativet /clr .

I det här avsnittet

Anmärkningar

Om du kompilerar med alternativet /clr kan du hantera CLR-undantag samt standardklassen Exception innehåller många användbara metoder för bearbetning av CLR-undantag och rekommenderas som basklass för användardefinierade undantagsklasser.

Det går inte att fånga undantagstyper som härleds från ett gränssnitt under /clr. Dessutom tillåter den vanliga språkkörningen inte att du kan fånga stack overflow-undantag. ett stacköverflödesfel avslutar processen.

Mer information om skillnader i undantagshantering i hanterade och ohanterade program finns i Skillnader i beteende för undantagshantering under hanterade tillägg för C++.

Kasta undantag under /clr

C++-utkastsuttrycket utökas för att kasta ett handtag till en CLR-typ. I följande exempel skapas en anpassad undantagstyp och en instans av den typen genereras:

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

En värdetyp måste boxas innan den kastas:

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

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

Prova/fånga block för CLR-tillägg

Samma try/catch blockstruktur kan användas för att fånga både CLR och interna undantag:

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

Utgång

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

Avspolningsordning för C++-objekt

Utrullning sker för C++-objekt med destruktorer som kan finnas i körningstidsstacken mellan den kastande funktionen och den hanterande funktionen. Eftersom CLR-typer allokeras på heap gäller inte uppvindning för dem.

Ordningen på händelser för ett undantag som kastas är följande:

  1. Körningsmiljön går igenom stacken för att hitta en lämplig catch-sats, eller i SEH:s fall ett undantagsfilter, för att hantera undantaget. Catch-satser genomsöks först i lexikal ordning och sedan dynamiskt nedåt i anropsstacken.

  2. När rätt hanterare hittas, avvecklas stacken till den punkten. För varje funktionsanrop på stacken destrueras dess lokala objekt och __finally-blocken körs, från den mest inre utåt.

  3. När stacken har avvecklats körs catch-satsen.

Fånga ohanterade typer

När en ohanterad objekttyp kastas omsluts den med ett undantag av typen SEHException. När du söker efter lämplig catch sats finns det två möjligheter.

  • Om en ursprunglig C++-typ påträffas packas undantaget upp och jämförs med den påträffade typen. Den här jämförelsen gör att en inbyggd C++-typ kan fångas på ett vanligt sätt.

  • Men om en catch sats av typen SEHException eller någon av dess basklasser granskas först, kommer satsen att fånga upp undantaget. Därför bör du placera alla catch-satser som fångar ursprungliga C++-typer först, innan några catch-satser av CLR-typer.

Observera att

catch(Object^)

och

catch(...)

fångar alla typer som kastas, inklusive SEH-undantag.

Om en ohanterad typ fångas av catch(Object^) kommer det inte att förstöra det utslängda objektet.

När du kastar eller fångar ohanterade undantag rekommenderar vi att du använder kompileringsalternativet /EHsc i stället för /EHs eller /EHa.

Se även

undantagshantering
safe_cast
undantagshantering