/CLR Altında Özel Durum İşleme Farkları
Yönetilen Özel Durumları Kullanma ile ilgili Temel Kavramlar , yönetilen uygulamalarda özel durum işlemeyi ele alır. Bu konu başlığında, özel durum işlemenin standart davranışı ve bazı kısıtlamalar arasındaki farklar ayrıntılı olarak ele alınmıştır. Daha fazla bilgi için bkz . _set_se_translator İşlevi.
Finally Bloğundan Atlama
Yerel C/C++ kodunda, yapılandırılmış özel durum işleme (SEH) kullanarak __finally bloğundan atlama işlemine izin verilir, ancak bir uyarı üretir. /clr altında, finally bloğundan atlamak hataya neden olur:
// clr_exception_handling_4.cpp
// compile with: /clr
int main() {
try {}
finally {
return 0; // also fails with goto, break, continue
}
} // C3276
Özel Durum Filtresi İçinde Özel Durum Oluşturma
Yönetilen kod içinde bir özel durum filtresi işlenirken bir özel durum oluştuğunda, özel durum yakalanıp filtre 0 döndürür gibi değerlendirilir.
Bu, iç içe özel durumun oluştuğu yerel koddaki davranışın aksine, EXCEPTION_RECORD yapısındaki ExceptionRecord alanı (GetExceptionInformation tarafından döndürülen) ayarlanır ve ExceptionFlags alanı 0x10 biti ayarlar. Aşağıdaki örnekte davranıştaki bu fark gösterilmektedir:
// 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");
}
}
Çıktı
Caught a nested exception
We should execute this handler if compiled to native
İlişkisiz Yeniden Dağıtımlar
/clr , bir catch işleyicisi dışında bir özel durumun yeniden dağıtılması (ilişkilendirilmemiş yeniden oluşturma olarak bilinir) desteklemez. Bu tür özel durumlar standart bir C++ yeniden oluşturma olarak değerlendirilir. Etkin bir yönetilen özel durum olduğunda ilişkilendirilmemiş bir yeniden yüklemeyle karşılaşılırsa, özel durum C++ özel durumu olarak sarmalanır ve sonra yeniden oluşturulur. Bu tür özel durumlar yalnızca türünde SEHExceptionbir özel durum olarak yakalanabilir.
Aşağıdaki örnekte, C++ özel durumu olarak yeniden oluşturulan yönetilen bir özel durum gösterilmektedir:
// 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" );
}
}
Çıktı
caught an SEH Exception
Özel Durum Filtreleri ve EXCEPTION_CONTINUE_EXECUTION
Yönetilen uygulamada bir filtre döndürülürse EXCEPTION_CONTINUE_EXECUTION
, filtre döndürüyor EXCEPTION_CONTINUE_SEARCH
gibi değerlendirilir. Bu sabitler hakkında daha fazla bilgi için bkz . try-except Deyimi.
Aşağıdaki örnekte bu fark gösterilmektedir:
// 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);
}
Çıktı
Counter=-3
_set_se_translator İşlevi
çağrısıyla _set_se_translator
ayarlanan translator işlevi, yalnızca yönetilmeyen kodda yakalamaları etkiler. Aşağıdaki örnekte bu sınırlama gösterilmektedir:
// 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();
}
Çıktı
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