/EH (例外処理モデル)
コンパイラで使用する例外処理の種類を指定し、例外の結果としてスコープの外部になる C++ オブジェクトを破棄します。 /EH が指定されていない場合、コンパイラは非同期構造化例外と C++ 例外の両方をキャッチしますが、非同期例外の結果としてスコープの外部になる C++ オブジェクトを破棄しません。
/EH{s|a}[c][-]
引数
a
非同期 (構造化) 例外と同期 (C++) 例外の両方をキャッチする例外処理モデル。s
C++ 例外のみをキャッチし、extern "C" として宣言された関数が例外をスローする可能性があるものと想定するようにコンパイラに指示する例外処理モデル。c
s (/EHsc) と共に使用すると、C++ 例外のみをキャッチし、extern "C" として宣言された関数が C++ 例外をスローしないものと想定するようにコンパイラに指示します。/EHca は /EHa と同じです。
解説
/EHa コンパイラ オプションは、ネイティブ C++ catch(...) 句で非同期構造化例外処理 (SEH) をサポートするために使用されます。 /EHa を指定せずに SEH を実装するために、__try、__except、__finally の各構文を使用する場合があります。 Windows および Visual C++ は SEH をサポートしていますが、ISO 標準の C++ 例外処理 (/EHs または /EHsc) の方がコードの移植性と柔軟性に優れているため、こちらの例外処理を使用することを強くお勧めします。 そうは言うものの、既存のコードや、特定の種類のプログラム、たとえば共通言語ランタイム (/clr (共通言語ランタイムのコンパイル)) をサポートするようにコンパイルされたコードなどでは、やはり SEH を使用しなければならないことがあります。 詳細については、「構造化例外処理 (C/C++)」を参照してください。
/EHa を指定し、catch(...) を使用して、すべての例外を処理しようとするのは危険です。 非同期例外のほとんどが回復不能で、致命的であると見なされます。 こうした例外をキャッチして操作を続行すると、プロセスが破損し、検出して修正するのが難しいバグが発生する可能性があります。
/EHs または /EHsc を使用すると、catch(...) 句では非同期構造化例外がキャッチされません。 アクセス違反およびマネージ Exception 例外がキャッチされず、非同期例外が処理される場合も含め、非同期例外が生成されたときに、スコープ内のオブジェクトが破棄されることはありません。
/EHa を使用すると、C++ 例外をスローする可能性のあるコードが確認されない場合でも、コンパイラは try ブロックの最適化を積極的に行わず、すべてのローカル オブジェクトのデストラクターを自動的に呼び出す例外フィルターをそのままにするため、イメージが大きくなり、パフォーマンスが最大にならない可能性があります。 これにより、非同期例外および C++ 例外のセーフ スタック アンワインドが可能になります。 /EHs を使用すると、throw ステートメントまたは関数呼び出しでのみ例外が発生するものと見なされます。 これにより、アンワインド可能オブジェクトの有効期間を管理するコードを削除できるため、コード サイズをかなり小さくできます。
/EHa を使用してコンパイルされたオブジェクトと、/EHs を使用してコンパイルされたオブジェクトを、同じ実行可能モジュールでリンクさせることはお勧めできません。 モジュールの任意の場所で /EHa を使用して、非同期例外を処理する必要がある場合は、/EHa を使用して、モジュール内のすべてのコードをコンパイルします。 構造化例外処理の構文は、/EHs を使用してコンパイルされたコードと同じモジュールで使用できますが、この SEH 構文と、try、throw、および catch を同じ関数に混在させることはできません。
throw 以外の方法で発生する例外をキャッチする場合は、/EHa を使用します。 この例では、構造化例外が生成され、キャッチされます。
// compiler_options_EHA.cpp
// compile with: /EHa
#include <iostream>
#include <excpt.h>
using namespace std;
void fail() { // generates SE and attempts to catch it using catch(...)
try {
int i = 0, j = 1;
j /= i; // This will throw a SE (divide by zero).
printf("%d", j);
}
catch(...) { // catch block will only be executed under /EHa
cout<<"Caught an exception in catch(...)."<<endl;
}
}
int main() {
__try {
fail();
}
// __except will only catch an exception here
__except(EXCEPTION_EXECUTE_HANDLER) {
// if the exception was not caught by the catch(...) inside fail()
cout << "An exception was caught in __except." << endl;
}
}
/EHc オプションでは、/EHs または /EHa を指定する必要があります。 /clr を使用すると、/EHa が暗黙的に指定されます (つまり、/clr /EHa とすると重複になります)。 /EHs[c] を /clr の後で使用すると、コンパイラはエラーを生成します。 最適化処理は、この動作に影響しません。 例外がキャッチされると、例外オブジェクトまたは例外と同じスコープ内にあるオブジェクトに対して、コンパイラが 1 つまたは複数のクラス デストラクターを呼び出します。 例外がキャッチされない場合は、これらのデストラクターは実行されません。
/clr を指定する場合の例外処理の制約については、「_set_se_translator」を参照してください。
マイナス記号 (-) を使用すると、このオプションをクリアできます。 たとえば、/EHsc- は /EHs /EHc- と解釈され、/EHs と等価です。
Visual Studio 開発環境でこのコンパイラ オプションを設定するには
プロジェクトの [プロパティ ページ] ダイアログ ボックスを開きます。 詳細については、「方法 : プロジェクト プロパティ ページを開く」を参照してください。
左ペインで、[構成プロパティ]、[C/C++]、[コード生成] の順に展開します。
[C++ の例外を有効にする] プロパティを変更します。
または、[C++ の例外を有効にする] を [いいえ] に設定してから [コマンド ライン] プロパティ ページをクリックし、[追加のオプション] ボックスにコンパイラ オプションを追加します。
このコンパイラ オプションをコードから設定するには
- ExceptionHandling を参照してください。