[解決済み] C++でassert()を使うのはバッドプラクティスか?
質問
私は、リリース ビルドのパフォーマンスに影響を与えずにデバッグを容易にするために、自分の C++ コードに多くのアサーションを追加する傾向があります。現在
assert
は、C++ のメカニズムを考慮せずに設計された純粋な C マクロです。
一方、C++では
std::logic_error
を定義しています。これはプログラムのロジックにエラーがある場合にスローされることを意図しています(それゆえにこの名前がついています)。インスタンスを投げることは、よりC++的で完璧な
assert
.
問題は
assert
と
abort
はどちらもデストラクタを呼ばずにプログラムを即座に終了させるので、 クリーンアップを省略することができますが、手動で例外を投げることは不必要な実行コストを追加することになります。これを回避する一つの方法として、独自のアサーションマクロを作成し
SAFE_ASSERT
を作成することです。これは C の対応部分と同じように動作しますが、失敗したときに例外をスローします。
この問題に対して、3つの意見が考えられます。
-
Cのアサートにこだわる。
プログラムは即座に終了するので、変更が正しく展開されたかどうかは問題ではありません。また
#define
を C++ で使うのも同じように悪いことです。 - main()で例外を投げ、キャッチする。 . プログラムのどのような状態でも、コードがデストラクタをスキップすることを許すのは悪い習慣で、何としても避けなければなりませんし、terminate()の呼び出しも同様です。例外がスローされた場合、それらはキャッチされなければなりません。
-
例外をスローして、プログラムを終了させる。
例外でプログラムが終了するのは問題なく、原因として
NDEBUG
により、リリースビルドでは決して起こりません。キャッチは不要であり、内部コードの実装の詳細をmain()
.
この問題に対する決定的な答えはあるのでしょうか?何か専門的なリファレンスはありますか?
編集しました。 デストラクタをスキップすることは、もちろん未定義の動作ではありません。
どのように解決するのですか?
アサーションはC++のコードでは完全に適切です。例外やその他のエラー処理メカニズムは、アサーションと同じことを意図しているわけではありません。
エラー処理は、エラーを回復したり、ユーザにうまく報告したりする可能性があるときのためのものです。例えば、入力ファイルを読もうとしたときにエラーが発生した場合、それについて何かしたいかもしれません。エラーはバグから発生することもありますが、単に与えられた入力に対して適切な出力をすることもあります。
アサーションは、APIが通常チェックされないときにAPIの要件が満たされていることをチェックしたり、開発者が構築によって保証されていると信じていることをチェックしたりするためのものです。例えば、あるアルゴリズムがソートされた入力を必要とする場合、 通常はそれをチェックしません。しかし、デバッグビルドがその種のバグに気づくように、 それをチェックするためのアサーションがあるかもしれません。アサーションは常に、正しく動作していないプログラムを示すべきです。
もし、不正なシャットダウンが問題を引き起こす可能性のあるプログラムを書いているならば、アサーションを避けた方がよいかもしれません。なぜなら、アサーションに当たることは、おそらくすでに未定義の動作の結果であるか、正しく機能するためのクリーンアップを妨げる可能性のある他の要件に違反することだからです。
また、例外の観点からアサーションを実装した場合、アサーションの目的そのものに矛盾しているにもかかわらず、潜在的に捕捉され「処理」される可能性があります。
関連
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] JUnit 4のテストで、ある例外が投げられたことをどのように断言しますか?
-
[解決済み] Pythonの "assert "はどのように使うのですか?
-
[解決済み] 例外がスローされたことを確認するためにAssertを使用するにはどうすればよいですか?
-
[解決済み] アサートの使用に関するベストプラクティス?
-
[解決済み] ループ内での変数宣言、グッドプラクティスかバッドプラクティスか?
-
[解決済み] PHPUnit は例外がスローされたことを表明しますか?
-
[解決済み】JavaScriptの "assert "とは何ですか?
-
[解決済み】assert関数とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】Enterキーを押して続行する