次の方法で共有


マネージ例外の基本概念

このトピックでは、マネージ アプリケーションで例外処理について説明します。 つまり、/clr のコンパイラ オプションを使用してコンパイルされたアプリケーション。

このトピックの内容

  • /clr の"例外

  • CLR の拡張機能の Try ブロックと Catch ブロック

解説

/clr オプションを使用すると、CLR の例外、または標準 C++ 例外処理構造化例外処理 (SEH) 処理できます。 CLR 例外がマネージ型によってスローされた例外になります。 System::Exception クラスは、CLR の例外を処理するための便利なメソッドを提供し、ユーザー定義の例外クラスの基本クラスとして推奨されます。

インターフェイスからのキャッチ例外の派生は /clrでサポートされません。 また、共通言語ランタイムは、スタック オーバーフロー例外をキャッチできません; スタック オーバーフロー例外は、プロセスが終了します。

マネージ例外処理の相違点の詳細については、アンマネージ アプリケーション、C++ のマネージ拡張の Exception Handling の動作の違いを参照し。

/clr の"例外

C++ の式は CLR 型にハンドルをスローするように拡張されています。 次の例は、カスタムの例外の種類を作成し、その型のインスタンスをスローします:

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

値型はスローされる前にボックス化する必要があります:

// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
   int i;
};

void GlobalFunction() {
   MyValueStruct v = {11};
   throw (MyValueStruct ^)v;
}

CLR の拡張機能の Try ブロックと Catch ブロック

同じ try/catch ブロック構造は、CLR およびネイティブ例外をキャッチし、例外の両方に使用できます。:

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

出力

In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11

C++ オブジェクトのアンワインドの順序

アンワインドがスローする関数と処理関数とのランタイム スタック上のデストラクターがインストールされている C++ オブジェクトに対して発生します。 CLR 型をヒープに割り当てられているため、アンワインド。これらには適用されません。

スローされた例外のイベントの順序は次のとおりです。:

  1. ランタイムは、スタックのフィルターを除き、例外をキャッチするために、では適切な catch 句を検索します。 次に、catch 句は構文的な順序で、呼び出し履歴で動的に最初に検索されます。

  2. 適切なハンドラーがある場合、スタックはその点にアンワインドされます。 履歴の各関数の呼び出しは、ローカル オブジェクトを破棄し、__finally ブロックは最も外側になってから実行されます。

  3. 一度スタックは、catch 句実行されますアンワインドされます。

キャッチのアンマネージ型

アンマネージ オブジェクト型は、スローされると、型 System::Runtime.InteropServices::SEHExceptionの例外にラップされます。 catch の適切な句を検索するときには、2 とおりの方法があります。

  • ネイティブ C++ 型が発生した場合、例外は、ある型と開けられ、比較されます。 この比較は、ネイティブ C++ 型を通常の方法でキャッチされるようにします。

  • ただし、基本クラスの型 SEHException またはの catch 句が最初に参照されると、例外を受け取ります。 したがって、CLR 型の句をキャッチする前にネイティブ C++ 型を先にキャッチするすべての catch 句を置く必要があります。

次の点に注意してください。

catch(Object^)

および

catch(...)

両方の型を含む、スローされた例外をキャッチします。

アンマネージ型の catch (Object^) によってスローされたときは、オブジェクトを破棄しません。

/EHs または /EHaの代わりに /EHsc のコンパイラ オプションを使用することをスローするか、キャッチ アンマネージ例外が、お勧めします。

参照

関連項目

safe_cast (C++ コンポーネント拡張)

Visual C++ での例外処理

その他の技術情報

例外処理 (C++ コンポーネント拡張)