web-dev-qa-db-ja.com

C ++の構造化例外(SEH)について知っておくべきことは何ですか?

すべてのC++開発者が知っておくべき構造化例外に関する重要なポイントは何ですか?

43
Andrew T

これらは、Unixシグナルに相当するWin32であり、アクセス違反、不正な命令、ゼロ除算などのCPU例外をキャッチできます。

正しいコンパイラオプション(Visual C++の場合は/ EHa)を使用すると、C++例外は同じメカニズムを使用し、スタックの巻き戻しはC++(ユーザー)例外とSEH(OS)例外の両方で正しく機能します。

C++例外とは異なり、SEHは型指定されていませんが、例外コード(原因)と、どのコードで障害が発生したか、および障害時にCPUレジスタが保持していたものに関する追加情報を含む同じデータ構造を共有しています。詳細は GetExceptionCode および GetExceptionInformation を参照してください。

また、SEHには「最初のチャンス」の処理があり、例外beforeをログに記録するか、または処理することができます。

41
Ben Voigt

私は最近SEHによって間接的に引き起こされた問題を抱えていました。具体的には、すべての開発者が知っておくべきと思うSEHの1つの機能のためです。

SEHが使用される場合、デストラクタは呼び出されないため、デストラクタにクリーンアップコードがある場合、クリーンアップされません。

私たちの問題は、コンストラクターがLockでデストラクターがUnlockのオブジェクトによってラップされたクリティカルセクションが原因でした。

デッドロックが発生し、その理由を理解できませんでした。コードとダンプを調べてデバッグした約1週間後、COMによって処理される例外があり、Criticalセクションがロックされたままであることが原因であることがわかりました。 。プロジェクトプロパティのVSのコンパイルフラグを変更して、SEHでもデストラクタを実行するように指示し、問題を解決しました。

したがって、コードでSEHを使用しない場合でも、(COMなどの)機能を備え、予期しない動作を引き起こす可能性のあるライブラリを使用している可能性があります。

32
Tidhar

彼らはそれらが標準C++の一部ではないことを知っている必要があります-それらはMicrosoftの発明であり、C++以外の言語で使用できます。

24
anon

Win32™構造化例外処理の深さに関するクラッシュコース

その記事は、SEHに慣れるためのtheリファレンスです。 13年後、まだ最高です。

SEHとC++の例外処理の違い に関するMSDNの専用トピックがあります。

SEHが議論されている場合、C++開発者が知っておくべきいくつかのこと:

C/C++ SEHの作成 例外ハンドラ

__try 
{
   // guarded code
}
__except ( expression )
{
   // exception handler code
}

これはnotC++例外処理であり、まっすぐなinot SEHをフックするためのMS固有の拡張機能です。ありふれたC++の例外とは非常に異なります。これらを使用するには、SEHを十分に理解する必要があります。

C/C++ SEHの記述 終了ハンドラ

__try {
   // guarded code
}
__finally ( expression ) {
   // termination code
}

SEHハンドラーと同様に、これをC++例外セマンティクスと混同しないでください。 SEHを十分に理解する必要があります。

_set_se_trasnlator :これは、非同期例外が使用されたときにSEH例外をC++タイプの例外に変換する関数です / EHa

そして最後に、個人的な意見:C++開発者はSEHを知っている必要がありますか?初めての新人 。ecxr の後、プッシュがC++例外を駆り立てるとき、あなたの便宜のために提供されているのは単なる幻想であることを理解するでしょう。起こっている唯一のものはSEHです。

20
Remus Rusanu

重要な点は、いつSEHを使用するか、いつ標準C++例外を使用するかを知ることです。最初に、システムを1つだけ選択します。混合システムは問題が発生する傾向があり、適切に実装するには両方を深く理解する必要があります。次に、高レベルでは、SEHはC++に限定されませんが、標準のC++例外はWindowsに限定されません。これが決定に影響を与えない場合は、不適切でない限り標準の例外を選択します(SEHが実行できることの詳細については、他の回答を参照してください)。

Microsoftのドキュメント (2018年8月13日付け)からの引用は、この結論を裏付けています。

構造化例外処理(SEH)は、ハードウェア障害などの特定の例外的なコード状況を適切に処理するためのCに対するMicrosoftの拡張機能です。 WindowsおよびMicrosoft C++はSEHをサポートしていますが、コードの移植性と柔軟性を高めるため、ISO標準のC++例外処理を使用することをお勧めします。それでも、既存のコードや特定の種類のプログラムを維持するには、SEHを使用する必要があります。

拡張機能の作成者が、ほとんどの場合それを使用しないことを推奨するのはなぜですか?おそらく、拡張機能がC用に作成され、現在のコンテキストがC++であるためと考えられます。言語は類似しているので、「特定の種類のプログラム」だけが本当にメリットがあるとしても、SEHをC++に副次的利益として移植することはおそらく十分簡単です。 (またはおそらく他の何らかの理由、おそらくC++が標準化される前に移植が開始されました。履歴は複雑になります。)

1
JaMiT