Différences de comportement de gestion des exceptions sous /CLR
Concepts de base pour les exceptions managées décrit la gestion des exceptions dans les applications managées.Dans cette rubrique, les différences du comportement standard de la gestion des exceptions et des restrictions sont discutées en détail.Pour plus d'informations, consultez La fonction de _set_se_translator.
Ignorer finally d'un bloc
Dans le code C/C++ native, il permet d'ignorer un bloc definally de (SEH) l'utilisation de la gestion structurée des exceptions bien qu'il ait un avertissement.Sous /clr, saut en dehors d'un bloc de finally provoque une erreur :
// clr_exception_handling_4.cpp
// compile with: /clr
int main() {
try {}
finally {
return 0; // also fails with goto, break, continue
}
} // C3276
Déclencher des exceptions dans un filtre d'exceptions
Lorsqu'une exception est levée pendant le traitement de filtre d'exception dans le code managé, l'exception est interceptée et traitée comme si retourne 0 de filtre.
Cette méthode diffère du comportement en code natif où une exception imbriquée est levée, le champ d' ExceptionRecord dans la structure d' EXCEPTION_RECORD (comme retourné par GetExceptionInformation) est défini, et les ensembles de champ d' ExceptionFlags que le 0x10 a mordus.L'exemple suivant illustre cette différence de comportement :
// 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");
}
}
Sortie
Caught a nested exception
We should execute this handler if compiled to native
Lève à nouveau fichier
/clr ne prend pas en charge lever une nouvelle fois une exception en dehors d'un gestionnaire catch (appelé un nouveau fichier).Les exceptions de ce type sont traitées comme nouveau C++ standard.Si un nouveau fichier est créé quand il existe une exception managée active, l'exception est encapsulée comme une exception puis à nouveau levée C++.Les exceptions de ce type peuvent être interceptées comme une exception de type System::SEHException.
L'exemple suivant montre un à nouveau levée d'exception managé comme une exception C++ :
// 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" );
}
}
Sortie
caught an SEH Exception
Filtres d'exceptions et EXCEPTION_CONTINUE_EXECUTION
Si un filtre retourne EXCEPTION_CONTINUE_EXECUTION dans une application managée, il est traité comme si le filtre est retourné EXCEPTION_CONTINUE_SEARCH.Pour plus d'informations sur ces constantes, consultez l' instruction try-except l'instruction.
L'exemple suivant illustre cette différence :
// 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);
}
Sortie
Counter=-3
La fonction de _set_se_translator
La fonction de transcodage, défini par un appel à _set_se_translator, catch d'affecte uniquement dans le code non managé.L'exemple suivant illustre cette limitation :
// 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();
}
Sortie
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
Voir aussi
Référence
safe_cast (extensions du composant C++)
Gestion des exceptions dans Visual C++