Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
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:
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.
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.
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
catchsats 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.