Share via


Unterschiede im Ausnahmebehandlungs-Verhaltens unter /CLR

Ausnahmebehandlung erläutert Grundlegende Konzepte, wenn verwaltete Ausnahmen verwendet werden in verwalteten Anwendungen.In diesem Thema werden die Unterschiede aus dem Standardverhalten der Ausnahmebehandlung und einige Einschränkungen ausführlich erläutert.Weitere Informationen finden Sie unter Die _set_se_translator Funktion.

Die Finalize-Methode eines Finally-Blocks herausspringen

In systemeigenen C/C++-Code wird das Herausspringen eines finally-Blocks mithilfe der strukturierten Ausnahmebehandlung (SEH) zulässig, obwohl eine Warnung erzeugt.Die /clr verursacht das Herausspringen eines finally-Block einen Fehler:

// clr_exception_handling_4.cpp
// compile with: /clr
int main() {
   try {}
   finally {
      return 0;   // also fails with goto, break, continue
    }
}   // C3276

Auslösen von Ausnahmen innerhalb eines Ausnahme-Filters

Wird eine Ausnahme während der Verarbeitung von Ausnahmefilter innerhalb von verwaltetem Code ausgelöst wird, wird die Ausnahme abgefangen und behandelt, als ob der Filter 0 zurückgibt.

Dies steht im Gegensatz zum Verhalten in systemeigenem Code, in der eine geschachtelte Ausnahme ausgelöst wird, das ExceptionRecord Feld in der EXCEPTION_RECORD-Struktur (wie durch GetExceptionInformation zurückgegeben) wird festgelegt, und die ExceptionFlags Feld Bit 0x10, die das legt ihn fest.Im folgenden Beispiel wird dieser Unterschiede im Verhalten:

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

2ww6y7y2.collapse_all(de-de,VS.110).gifOutput

Caught a nested exception
We should execute this handler if compiled to native

Zuordnung definiert wird, erneut aus

/clr unterstützt nicht das erneute Auslösen einer Ausnahme (außerhalb eines catch-Handlers (auch als Zuordnung aufgehoben werden erneut aus.)Ausnahmen dieses Typs werden behandelt, während C++-Standard- erneut auslösen.Wenn Zuordnung definiert auftritt, wenn es erneut auslösen. eine aktive verwaltete Ausnahme vorhanden ist, wird die Ausnahme als Ausnahme in C-Format ++ umschlossen und dann erneut gelöst.Ausnahmen dieses Typs können als Ausnahme des Typs System::SEHException nur abgefangen werden.

Das folgende Beispiel zeigt eine verwaltete Ausnahme, die als Ausnahme in C-Format ++ erneut gelöst werden:

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

2ww6y7y2.collapse_all(de-de,VS.110).gifOutput

caught an SEH Exception

Ausnahme-Filter und EXCEPTION_CONTINUE_EXECUTION

Wenn ein Filter EXCEPTION_CONTINUE_EXECUTION in einer verwalteten Anwendung zurückgibt, wird er so behandelt, als ob der Filter EXCEPTION_CONTINUE_SEARCH zurückgibt.Weitere Informationen über diese Konstanten finden Sie unter TRY-ausgenommen Anweisung.

Das folgende Beispiel veranschaulicht den Unterschied:

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

2ww6y7y2.collapse_all(de-de,VS.110).gifOutput

Counter=-3

Die _set_se_translator Funktion

Die Übersetzung Gruppe, die durch einen Aufruf von _set_se_translator, wirkt sich nur auf Erfassungen in nicht verwaltetem Code.Im folgenden Beispiel wird diese Einschränkung:

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

2ww6y7y2.collapse_all(de-de,VS.110).gifOutput

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

Siehe auch

Referenz

safe_cast

Ausnahmebehandlung in Visual C++

Weitere Ressourcen

Ausnahmebehandlung unter /clr (nur auf Englisch verfügbar)