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.
Grundläggande begrepp i Använda hanterade undantag beskriver undantagshantering i hanterade program. I det här avsnittet beskrivs skillnader från standardbeteendet för undantagshantering och vissa begränsningar i detalj. Mer information finns i Funktionen _set_se_translator.
Hoppa ut ur en finally-block
I inbyggd C/C++-kod tillåts att hoppa ut ur ett __finally-block med hjälp av strukturerad undantagshantering (SEH) även om det ger en varning. Under /clr orsakar hoppning ut ur ett äntligen block ett fel:
// clr_exception_handling_4.cpp
// compile with: /clr
int main() {
try {}
finally {
return 0; // also fails with goto, break, continue
}
} // C3276
Skapa undantag inom ett undantagsfilter
När ett undantag utlöses under bearbetningen av ett undantagsfilter i hanterad kod fångas undantaget upp och behandlas som om filtret returnerar 0.
Detta står i kontrast till beteendet i intern kod där ett kapslat undantag utlöses, fältet ExceptionRecord i den EXCEPTION_RECORD strukturen (som returneras av GetExceptionInformation) anges och fältet ExceptionFlags anger 0x10 bit. I följande exempel visas den här skillnaden i beteende:
// clr_exception_handling_5.cpp
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#ifndef false
#define false 0
#endif
int *p;
int filter(PEXCEPTION_POINTERS ExceptionPointers) {
PEXCEPTION_RECORD ExceptionRecord =
ExceptionPointers->ExceptionRecord;
if ((ExceptionRecord->ExceptionFlags & 0x10) == 0) {
// not a nested exception, throw one
*p = 0; // throw another AV
}
else {
printf("Caught a nested exception\n");
return 1;
}
assert(false);
return 0;
}
void f(void) {
__try {
*p = 0; // throw an AV
}
__except(filter(GetExceptionInformation())) {
printf_s("We should execute this handler if "
"compiled to native\n");
}
}
int main() {
__try {
f();
}
__except(1) {
printf_s("The handler in main caught the "
"exception\n");
}
}
Utgång
Caught a nested exception
We should execute this handler if compiled to native
Avassocierade återväxter
/clr stöds inte för att omkasta ett undantag utanför en catch-hanterare (kallas för en frikopplad omkastning). Undantag av den här typen behandlas som en C++-standardåterkastning. Om ett avassocierat pånyttkastande inträffar när det finns ett aktivt hanterat undantag, omsluts undantaget som ett C++-undantag och kastas sedan på nytt. Undantag av den här typen kan bara fångas som ett undantag av typen SEHException.
I följande exempel visas ett hanterat undantag som återkastas som ett C++-undantag:
// clr_exception_handling_6.cpp
// compile with: /clr
using namespace System;
#include <assert.h>
#include <stdio.h>
void rethrow( void ) {
// This rethrow is a dissasociated rethrow.
// The exception would be masked as SEHException.
throw;
}
int main() {
try {
try {
throw gcnew ApplicationException;
}
catch ( ApplicationException^ ) {
rethrow();
// If the call to rethrow() is replaced with
// a throw statement within the catch handler,
// the rethrow would be a managed rethrow and
// the exception type would remain
// System::ApplicationException
}
}
catch ( ApplicationException^ ) {
assert( false );
// This will not be executed since the exception
// will be masked as SEHException.
}
catch ( Runtime::InteropServices::SEHException^ ) {
printf_s("caught an SEH Exception\n" );
}
}
Utgång
caught an SEH Exception
Undantagsfilter och EXCEPTION_CONTINUE_EXECUTION
Om ett filter returneras EXCEPTION_CONTINUE_EXECUTION i ett hanterat program behandlas det som om filtret returnerade EXCEPTION_CONTINUE_SEARCH. Mer information om dessa konstanter finns i try-except-instruktion.
I följande exempel visas den här skillnaden:
// clr_exception_handling_7.cpp
#include <windows.h>
#include <stdio.h>
#include <assert.h>
int main() {
int Counter = 0;
__try {
__try {
Counter -= 1;
RaiseException (0xe0000000|'seh',
0, 0, 0);
Counter -= 2;
}
__except (Counter) {
// Counter is negative,
// indicating "CONTINUE EXECUTE"
Counter -= 1;
}
}
__except(1) {
Counter -= 100;
}
printf_s("Counter=%d\n", Counter);
}
Utgång
Counter=-3
Funktionen _set_se_translator
Translator-funktionen, som anges av ett anrop till _set_se_translator, påverkar endast fångster i ohanterad kod. Följande exempel visar den här begränsningen:
// clr_exception_handling_8.cpp
// compile with: /clr /EHa
#include <iostream>
#include <windows.h>
#include <eh.h>
#pragma warning (disable: 4101)
using namespace std;
using namespace System;
#define MYEXCEPTION_CODE 0xe0000101
class CMyException {
public:
unsigned int m_ErrorCode;
EXCEPTION_POINTERS * m_pExp;
CMyException() : m_ErrorCode( 0 ), m_pExp( NULL ) {}
CMyException( unsigned int i, EXCEPTION_POINTERS * pExp )
: m_ErrorCode( i ), m_pExp( pExp ) {}
CMyException( CMyException& c ) : m_ErrorCode( c.m_ErrorCode ),
m_pExp( c.m_pExp ) {}
friend ostream& operator <<
( ostream& out, const CMyException& inst ) {
return out << "CMyException[\n" <<
"Error Code: " << inst.m_ErrorCode << "]";
}
};
#pragma unmanaged
void my_trans_func( unsigned int u, PEXCEPTION_POINTERS pExp ) {
cout << "In my_trans_func.\n";
throw CMyException( u, pExp );
}
#pragma managed
void managed_func() {
try {
RaiseException( MYEXCEPTION_CODE, 0, 0, 0 );
}
catch ( CMyException x ) {}
catch ( ... ) {
printf_s("This is invoked since "
"_set_se_translator is not "
"supported when /clr is used\n" );
}
}
#pragma unmanaged
void unmanaged_func() {
try {
RaiseException( MYEXCEPTION_CODE,
0, 0, 0 );
}
catch ( CMyException x ) {
printf("Caught an SEH exception with "
"exception code: %x\n", x.m_ErrorCode );
}
catch ( ... ) {}
}
// #pragma managed
int main( int argc, char ** argv ) {
_set_se_translator( my_trans_func );
// It does not matter whether the translator function
// is registered in managed or unmanaged code
managed_func();
unmanaged_func();
}
Utgång
This is invoked since _set_se_translator is not supported when /clr is used
In my_trans_func.
Caught an SEH exception with exception code: e0000101