マネージ例外の使用についての基本概念
このトピックでは、マネージ アプリケーションで例外処理について説明します。つまり、 /clr のコンパイラ オプションを使用してコンパイルされたアプリケーション。
このトピックの内容
/clr の下の技術情報例外
CLR の拡張機能の try/catch ブロック
解説
/clr オプションを使用してコンパイルすると、 CLR 例外、または標準 C++ 例外処理 と 構造化例外処理 (SEH)処理できます。CLR 例外がマネージ型によってスローされた例外です。System::Exception のクラスは、 CLR 例外を処理するための便利なメソッドを提供し、ユーザー定義の例外クラスの基本クラスとして推奨されます。
インターフェイスから派生した例外のキャッチの種類は /clrでサポートされません。また、共通言語ランタイムは、割り当てスタック オーバーフロー例外をキャッチ; スタック オーバーフロー例外は処理を停止します。
マネージとアンマネージ アプリケーションでの例外処理の違いについての詳細については、 C++ マネージ拡張の下の例外処理動作の違いを参照してください。
/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 型がヒープに割り当てられたため、アンワインドする、適用されません。
スローされる例外のイベントの順序は次のとおりです。:
ランタイムは、スタックのフィルターを除き、例外をキャッチするために自分の場合は適切な catch の句、または検索説明します。次に、 catch 句はの構文の順序で、呼び出し履歴の下に動的に最初に検索されます。
適切なハンドラーがある場合、履歴はそのポイントにアンワインドされます。履歴の各関数呼び出しでは、ローカル オブジェクトは破棄し、 __finally ブロックは、外部に最も外側から実行されます。
一度スタックは、 catch 句の実行されますアンワインドされます。
以外のアンマネージ型
アンマネージ オブジェクト オブジェクトの型は、スローされると、例外の型 System::Runtime.InteropServices::SEHExceptionでラップされます。catch の適切な句を検索するときに、 2 種類の可能性があります。
ネイティブ C++ の型が検出されると、例外が発生した型に開けられ、比較されます。この比較は、ネイティブ C++ 型が通常の方法でキャッチされるようにします。
ただし、基本クラスの catch の句の型が SEHException 、最初にチェックされている場合、句は例外を受け取ります。したがって、 CLR 型の句をキャッチする前に、ネイティブ C++ の型を先にキャッチするすべての catch の句を置く必要があります。
次の点に注意してください。
catch(Object^)
および
catch(...)
両方の SEH を含む型スローされた例外をキャッチします。
アンマネージ型が catch (Object^)によって検出された場合、スローされたオブジェクトを破棄しません。
/EHs か /EHaの代わりに /EHsc のコンパイラ オプションの使用をスローまたはキャッチ アンマネージ例外が、お勧めする場合。