エラーと例外の処理 (Modern C++)
最新の C++ では、ほとんどのシナリオで例外を使用するレポートおよび論理エラーおよびランタイム エラーを処理する方法です。スタックにはエラーを検出したとそれを処理する方法を知っているが、機能間のいくつかの関数呼び出しが含まれている場合に特に当てはまります。例外はコール スタック上の情報を渡すには、エラーを検出するコードを正式明確な方法を提供します。
プログラムのエラーは、通常 2 つのカテゴリに分類します。 たとえばミスをプログラミングし、"インデックスが範囲外です」エラーが、プログラマはたとえば、管理範囲外の実行時エラーが"ネットワーク サービスを利用できません"エラー発生する論理エラー。C スタイルのプログラミング、COM では、エラー報告エラー コードまたはステータス コードは特定の機能を表す値を返すか、呼び出し元が必要に応じてに取得できるは、エラーが報告されたかどうかを確認する各関数呼び出しの後、グローバル変数を設定することによって管理されます。たとえば、COM プログラミング、HRESULT の戻り値を使用して、呼び出し元にエラーを通知して、Win32 API をコール スタックによって報告された最後のエラーを取得するには、GetLastError 関数が。どちらの場合も、そのコードを認識し、適切に応答するには、呼び出し元にです。エラー コードは呼び出し元が明示的に処理しない場合は、プログラム可能性があります警告を表示せず、クラッシュまたはに不正なデータを実行して誤った結果を生成するには、続行します。
最新の C++ では次の理由で優先される例外。
例外は、エラー状態を認識し、それを処理するには、呼び出し元のコードを強制的します。未処理の例外は、プログラムの実行を停止します。
例外はエラーを処理することができます、コール スタック内のポイントにジャンプします。関数の中間が伝達、例外ことができます。これは、他のレイヤーを調整する必要はありません。
スタックのアンワインド例外処理機構は、例外がスローされた後に明確に定義されたルールに従ってスコープ内のすべてのオブジェクトを破棄します。
例外は、エラーを検出するコードと、エラーを処理するコードが明確に分離できます。
次の簡単な例をスローし、C++ での例外をキャッチするために必要な構文を示しています。
#include <stdexcept>
#include <limits>
#include <iostream>
using namespace std;
class MyClass
{
public:
void MyFunc(char c)
{
if(c < numeric_limits<char>::max())
throw invalid_argument("MyFunc argument too large.");
//...
}
};
int main()
{
try
{
MyFunc(256); //oops!
}
catch(invalid_argument& e)
{
cerr << e.what() << endl;
return -1;
}
//...
return 0;
}
C++ での例外では、c# や Java などの言語と似ています。try場合は、例外ブロックスロー 、 キャッチが関連付けられているcatchブロックは、例外の型と一致します。つまり、実行をジャンプから、 throwステートメントに、 catchステートメント。使用可能な catch ブロックが見つからない場合は、 std::terminateが呼び出されると、プログラムが終了します。C++ では、任意の型がスローされる場合があります。 直接または間接的に派生する型をスローすることただし、推奨std::exception。前の例では、例外の種類、 invalid_argument、標準ライブラリに定義されている、 <stdexcept> のヘッダー ファイル。C++ は提供しませんとする必要はありません、 finallyブロックは、例外がスローされた場合は、すべてのリソースが解放されていることを確認します。リソースの取得は、初期化 (RAII) イディオムは、スマート ポインターを使用して、リソースのクリーンアップに必要な機能を提供です。詳細については、「方法: 例外安全性に対応した設計をする」を参照してください。スタック アンワインド、C++ メカニズムの詳細についてを参照してくださいC++ の例外とスタック アンワインドする。
基本的なガイドライン
堅牢なエラー処理は、任意のプログラミング言語には厳しいです。例外の適切なエラー処理をサポートするいくつかの機能を提供するは、自動的にすべての作業を実行できません。例外処理機構のメリットを実現するには、コードをデザインするときの例外になります。
エラーはエラーをチェックするには、使用をアサートします。例外を使用して、たとえば、発生するエラーをパブリック関数のパラメーターの入力検証でエラーを確認します。詳細については、「Exceptions VS. Assertions」を参照してください。
1 つまたは複数のコレクションに含まれる関数呼び出しによって、エラーを処理するコードがエラーを検出するコードから分離する可能性がある場合は、例外を使用します。エラーを処理するコード - によって検出されたコードに密に結合すると、パフォーマンスが重要なループ内でエラー ・ コードを代わりに使用するかどうかを検討します。例外を使用しない場合の詳細についてを参照してくださいWhen Not to Use Exceptions。
かどうかをスローする例外を伝達する各関数では、いずれか、次の 3 つの例外を保証を提供します。 厳密な保証、基本の保証、または nothrow (noexcept) の保証。詳細については、「方法: 例外安全性に対応した設計をする」を参照してください。
値が例外をスロー、それらへの参照をキャッチします。どのような処理できない例外をキャッチしません。詳細については、「スローできる例外をキャッチすると (C++) のガイドライン」を参照してください。
例外の仕様は、C では使用されなく使用しないで + + 11。詳細については、「Exception specifications and noexcept」を参照してください。
これらを適用すると、標準ライブラリの例外の種類を使用します。カスタム例外型から派生した、 例外クラス階層。詳細については、「方法: 標準ライブラリの例外オブジェクトを使用する」を参照してください。
関数のメモリの解放をデストラクターからをエスケープするには、[例外を許可しません。
例外とパフォーマンス
例外処理機構では、非常に最小限のパフォーマンス コストの場合は、例外はスローされませんがあります。コストのスタックの走査とアンワインドは、例外がスローされた場合は、関数呼び出しのコストをほぼ同等です。その他のデータ構造が後のコール スタックを追跡するために必要なtryブロックを入力して例外がスローされた場合は、スタックのアンワインドする追加の手順が必要があります。ただし、ほとんどのシナリオでは、コスト パフォーマンスとメモリのフット プリントで重要です。例外処理のパフォーマンスに悪影響は非常にメモリに制約があるシステムでは、大きな可能性があります。 またはのパフォーマンスに重大なエラーが定期的に発生する可能性があるし、それを処理するコード、報告するコードに密ループします。どのような場合は、プロファイルと測定せず例外の実際のコストを知ることは不可能です。コストが大きい場合、まれにも、その増加の正当性、保守の容易性、および適切な例外のポリシーで提供されているその他の利点を重み。
例外 VS.アサーション
例外とアサート プログラムで実行時エラーを検出するための 2 つの異なるメカニズムです。すべてのコードが正しい場合は、true にする必要があります開発中の条件をテストするには、使用をアサートします。エラーのもので、コードを修正するのがあることを示すために例外を使用して、このようなエラーを処理するのには、ポイントがないと、プログラムが実行時にリカバリする必要があります条件を表さない。デバッガーでプログラムの状態を検査できるようにするには、assert ステートメントで実行が停止します。 例外は、最初の該当する catch ハンドラーから続行します。例外を使用して、コードが正しい、たとえば、「ファイルが見つかりません」である場合でも、または"メモリ」の実行時に発生したエラーの状態を確認するのにはリカバリだけメッセージがログに出力し、プログラムを終了しても、これらの条件からの回復することができます。常に例外を使用してパブリック関数の引数を確認してください。関数はエラーがない場合でも、ユーザーに渡す可能性があります引数を完全に制御はあります。
Windows の SEH 例外と C++ 例外
C と C++ の両方のプログラムは、構造化例外処理 (SEH) メカニズムでは、Windows オペレーティング システムを使用できます。SEH を使用する以外は SEH の概念では、C++ 例外、ように、 __try、 __except、および__finallyを作成するのではなくtryとcatch。Visual C では、C++ 例外が SEH を実装されています。ただし、C++ コードを記述する場合は、C++ 例外の構文を使用します。
SEH の詳細については、「構造化例外処理 (C++)」を参照してください。
例外の仕様と noexcept
例外仕様は C++ では関数がスローする例外を指定する手段として導入されました。しかし、例外仕様の実習では、問題があることを証明し、C では使用されなくは 11 のドラフト標準。例外仕様以外は使用しないことをお勧めthrow()、例外をエスケープする例外がないことを示します。例外の仕様の種類を使用する必要がある場合は、 throw(型)に注意してください、 Visual C++からはこの特定の方法で異なります。詳細については、「例外の設計」を参照してください。noexcept子が C で導入は 11 に代わるとしてthrow()。
参照
概念
方法: 例外的なコードと非例外的なコードをインターフェイスで連結する