7

例外処理に関する私の理解は非常に限られています。例外をスローするのは簡単だと思いますが (またはexpected<T>後で使用するためにパックすることもできます)、例外をどうするかについてはほとんどわかりません。

現在、私の知識は限られています

  • 自分のリソースをクリーンアップし、適切な場所で処理されるように例外を再スローします。例えば

    ptr p = alloc.allocate(n);
    try
    {
       uninitialized_copy(first,last,p);//atomic granularity, all or none
    }
    catch(...)
    {
        alloc.deallocate(p,n);
        throw;
    }
    

RAIIしかし、これは次のようなパターンで同等に変換できると思います

alloc_guard<ptr> p{alloc.allocate(n)};
uninitialized_copy(first,last,p.get());
p.commit();
  • トップレベルで例外をキャッチし、素敵なメッセージを作成して出力し、終了します.eg

    int main(int argc,char** argv)
    {
       try
       {
           app_t the_app(argc,argv);
           the_app.run();
       }
       catch(std::runtime_error& e)
       {
          //instead of what, I can also compose the mesage here based on locale.
          std::cout<<e.what()<<std::endl;
       }
    }
    

mainしたがって、例外をキャッチし、適切なメッセージを出力して閉じるなどのトップレベル関数で行うだけです。

さまざまな外部ライブラリを実装のバックエンドとして使用して、優れた API セットを備えたライブラリを実装しているときに、サードパーティ ライブラリの例外が API 仕様の一部であることに気付きました。サード パーティのライブラリの例外は、ライブラリの境界を越えてユーザー コードに到達するためです。

そのため、私のライブラリ API は、使用していた外部ライブラリ (およびそれぞれが独自の例外階層を持つ) からのすべての例外をユーザー コードに漏らしました。

これは私の質問につながります.例外をキャッチすると何ができるでしょうか?

すなわち、

  • 外部ライブラリからキャッチされた例外を自分の例外に変換し、それを一般的な方法でスローできますか (サードパーティ ライブラリの例外階層と例外 API の間のマッピングが として提供されているとしますmpl::map) ?
  • メッセージ/コールスタックを出力するよりも便利なことはありますか?たとえば、別の入力パラメーターを使用してスローサイトで関数を再開します(たとえば、file_not_foundまたはを取得したときにdisk_error、別のファイルで関数を再実行します)?
  • 知っておく価値のある他のパターンはありますか?

ありがとう

4

3 に答える 3

2

大規模なアプリケーションでは、通常、トップレベルの catch では十分ではありません。例外について何かできる場合は、例外をキャッチする必要がありますが、例外を処理する方法は主にいくつかあります。

  1. できれば回復。- (例: 更新を確認します -> ネットワーク接続を開くことができませんでした。例外 -> 無視して、今すぐ更新をダウンロードしないでください。)
  2. 回復方法を選択するようユーザーに伝えます。(例: ファイルを保存 -> ファイルを作成できません例外 -> ユーザーに別のファイル名を選択するかキャンセルするよう指示)
  3. ログインして終了します。これは、最上位の包括的なシナリオです。
于 2013-08-13T08:56:25.220 に答える
2

これは非常に大きなテーマです。

  1. サードパーティの例外を独自の例外に簡単に変換できるとは思えません。さらに、個人的には、この動作を実装する必要はないと思います。サードパーティのライブラリは実装の一部であり、パブリック API に公開されていないため、(マッピングを介しても) すべての例外を公開する必要があるのはなぜですか? ある日、同じものを実装する別のサードパーティ ライブラリに固執する場合、例外階層全体を再設計しますか? ないと思います。ライブラリの API は脆弱であってはならないため、外部例外を独自のものにマップしないことをお勧めします。

  2. 次の方法で、サードパーティの例外を階層にマップできます。

    • 何も包みません。3番目のライブラリがそうするからといって、何も投げる必要はないということです。その例外をキャッチして処理するか、エラー コードを返すか、状態を適切に変更することができます。常に再スローするのではなく、他にも多くの可能性があります。

    • すべてのサード パーティの例外を 1 対 1 で翻訳する必要はありません。ライブラリ AAA を内部で使用する場合、そのライブラリからの多くの例外を表す単一の AAAException を持つことができます。

  3. 知っておくと便利なこと: 常に const 参照で例外をキャッチする:

    catch (const exception & ex)

この主題は非常に大きいので、私の答えがそれを理解するのに役立つことを願っています.

コメントへの回答:

  1. サード パーティの例外を独自の API にマップしない場合 (1 対 1 である必要はありません)、それらはクライアント コードにリークします- いいえ、そうではありません。ライブラリ内でそれらをキャッチし、キャッチされた例外をどうするかを決定する必要があります: 独自の例外をスローする、エラー コードを返す、クライアント リスナーに通知する、エラーをログに記録するなど...

    try {
        3rdpatry.call();
    } catch (const 3rdpartyException & ex) {
        // throw YourException(ex.what());
        // listener.notify(some_error)
        // return some_code
    }
    
  2. const 参照によるキャッチは、スライスをまったく防止するためのものではありません。それを説明する素晴らしい議論がここにあります。

于 2013-08-13T05:35:22.777 に答える