web-dev-qa-db-ja.com

std :: runtime_errorとstd :: logic_errorについて混乱している

最近、コマンドライン入力が解析できない場合、ブーストprogram_optionsライブラリがlogic_errorをスローすることを確認しました。それはlogic_errorruntime_errorについての私の仮定に挑戦しました。

論理エラー(logic_errorとその派生クラス)は、プログラムの不変条件に準拠するための内部障害に起因する問題であり、多くの場合、内部APIへの不正な引数の形であると想定しました。その意味で、これらはASSERTとほぼ同等ですが、リリースされたコードで使用することを目的としています(通常、リリースされたコードにコンパイルされないASSERTとは異なります)。デバッグ/テストビルドで個別のソフトウェアコンポーネントを統合することが不可能な状況で役立ちます。または、失敗の結果として、無効な不変条件に関するランタイムフィードバックをユーザーに提供することが重要になります。

同様に、runtime_errorsは、プログラマーの制御外の実行時条件(I/Oエラー、無効なユーザー入力など)にのみ起因すると思いました。

ただし、program_optionsは明らかに(主に?)エンドユーザー入力を解析する手段として頻繁に使用されるため、私のメンタルモデルでは、入力が正しくない場合は確かにruntime_errorをスローする必要があります。

どこが間違っているのですか?例外タイピングのブーストモデルに同意しますか?

45

この場合、私は(少なくともほとんどの場合)あなたが正しいと思います、そしてそれは間違っています。この規格では、logic_errorを次のように説明しています。

クラスlogic_errorは、論理前提条件の違反やクラス不変条件など、プログラムの実行前におそらく検出可能なエラーを報告するための例外としてスローされるオブジェクトのタイプを定義します。

解析できないコマンドライン引数は、それほどうまく適合していないようです。

対照的に、runtime_errorは次のように記述されます。

クラスruntime_errorは、例外としてスローされるオブジェクトのタイプを定義し、プログラムの実行時にのみ検出可能と思われるエラーを報告します。

それがより適しているようです。

32
Jerry Coffin

純粋な標準的な観点から、あなたは正しいです。 program_optionsは、エラーが実行時か論理かによって、runtime_errorまたはlogic_errorのいずれかから派生したクラスをスローする必要があります。 (現在の例外についてそのようなアイデアの分類を決定するために、現在のコードを確認しませんでした)。

実用的な観点から、例外がlogic_errorであるかruntime_errorであるかに基づいて有用な決定を行うC++コードはまだ見ていません。結局のところ、assertファイルを許可するのではなくlogic_errorをスローする唯一の理由は、何らかの方法で回復を試みたい場合であり、それはランタイムエラーからの回復と同じです。個人的には、logic_errorruntime_errorは、Java-理論的には素晴らしいですが、実際には役に立ちません。つまり、おそらく、 program_options::errorexceptionから派生させるだけです。つまり、「空き時間」が見つかると、誰もが話し続けます。

9
Vladimir Prus

C++ 0x標準の現在のドラフトは次のように述べています(19.2節):

1)これらのクラスに反映されるエラーモデル(つまり、例外タイプ)では、エラーは論理エラーと実行時エラーの2つの大きなカテゴリに分類されます。

2)論理エラーの際立った特徴は、プログラムの内部論理のエラーが原因であるということです。理論的には、それらは予防可能です。

3)対照的に、ランタイムエラーは、プログラムの範囲を超えたイベントが原因です。事前に簡単に予測することはできません。

他の回答の1つで引用されている引用符とともに、Boost.ProgramOptionsが「プログラムの実行前におそらく検出可能なエラー」によって引き起こされる予防可能なエラーに対してstd :: logic_errorをスローする理由を説明します。

6
hkaiser

ユーザーは、ファイルが存在することを確認し、プログラムを実行すると、ファイルが削除されたことを突然知ることができます。そのため、I/Oの問題は常にruntime_error。別のスレッドが問題を引き起こす可能性があるため、呼び出し元がチェックできたとしても、ステートフル問題はruntime_errorsです。

logic_errorは、関数の引数が間違っている場合です。より強力なタイプチェックで以前に捕らえられた可能性のあるものについてはのみです。

したがって、「不足しているファイル」はruntime_errorですが、「不適切にフォーマットされたファイル名」はlogic_error

技術的には、論理エラーwithin関数はlogic_errorでも、自分の関数内でテストするのに十分賢いのであれば、そもそもそれを防ぐのに十分賢いはずです。

1
cdunn2001

IMO、

  • std::logic_errorはユーザーC++プログラムによってスローされますlogic意図的に。ユーザープログラムによって予測されます。

  • std::runtime_errorはC++ ランタイム(または言語のコア部分…)によってスローされ、低レベルのエラーを抽象化します。ユーザーコードを使用せずに、意図せずに発生するだけです。

0
Eonil