0

プロジェクトを開始していますが、ファイル入力処理中のエラー処理のベスト プラクティスについて疑問に思っています。プロジェクトの現在の計画には、次のようなプロセスが含まれますmain

unique_ptr<Configuration> config(initConfig(argc,argv));
unique_ptr<InterfaceA> a(initA(config));

// Do real work here

Configuration クラスと他のすべてのクラスの初期化データは、次のような入力ファイルのヘッダーに含まれます。

#ObjectA-1

ObjectA、 を満たすオブジェクトに変換されることを意図したファイルがあることを教えてくれます。InterfaceAまた、1は、そのインターフェイスのどの特定の実装を使用するかを教えてくれます。

私の質問は、initConfigやなどの関数のエラー処理ですinitA。これらの関数内で、それぞれのファイルの最初の行を解析し、上記の情報をデコードします。たとえば、initAたまたま適切なヘッダーがないファイルを取得した場合#ObjectB-3、またはヘッダーがまったくない場合です。エラーを処理するには、次の 2 つの方法があります。

  • メインでキャッチされる例外をスローします。これにより、エラーを出力し、エラー フラグを介して他の init 関数をバイパスし、必要な高レベルのクリーンアップを行うことができます。これの悪い点は、mainほとんどが例外処理で構成されているため、コードが読みにくくなっているということです。

  • init 関数内からエラーをexit(EXIT_FAILURE)出力し、OS を呼び出して依存して、以前に割り当てられたメモリのクリーンアップを行います。これにより、コードがよりクリーンになり、よりローカルなエラー処理が可能になります。

exit個人的には、関数 を使用しない場合は 2 番目の方が好みです。

4

1 に答える 1

1

次のルールを使用してエラー処理を実行します。

  1. 可能な場合、呼び出し元のコードが処理する必要があるのは例外的な出来事ですか? その場合は、例外をスローします。「例外的」という言葉を定義するのが難しい場合もあります。この場合、例外をスローする必要があり、意味がある場合mainは例外を処理する必要があると思います。

    標準で定義されている 2 つの例外グループがあります。まず、 から継承するものがありstd::logic_errorます。これらは通常、呼び出し元のコードが関数のコントラクトを破ったときにスローされます。次に、 から継承するものがstd::runtime_errorあります。これらは、実行時にのみ検出できるエラーに使用されます。これはまさにあなたのように聞こえます。ファイルを読み取るときに、ファイルに問題があることしか認識していません。

    もちろん、必要に応じて独自の例外タイプをスローすることもできます。

  2. これは正常と見なされ、呼び出し元のコードによって無視される可能性があるエラーですか? これは、エラー コードの適切な使用法である可能性があります。

  3. コード内部の論理エラーですか? これは としてより理にかなっていassertます。s を使用assertして、実行していることが実際に意味があることを確認する必要があります。ばかげた例はint y = 5; y++; assert(y == 6);. 愚かな間違いに対する保険と考えてください。

私が言ったように、あなたの問題は例外を使用するのに適した場所のように思えます。RAII を正しく使用すれば、メモリ割り当てに問題はまったくないはずです。つまり、すべてのメモリー解放は、オブジェクトの破棄時に行う必要があります。例外がスローされた場合でも、デストラクタは引き続き呼び出されます。

于 2013-04-09T22:51:51.780 に答える