2017-09-11 4 views
4

コンテキスト:gccの__builtin_unreachable()に解決されるマクロにassert()をラップしない理由はありますか?

if(condition) __builtin_unreachable(); 

完全に取り除かれ、condition限り最適化のヒントとして使用されている:次のように見えるように、このanswerでは、私は、GCCの__builtin_unreachable()は、いくつかの驚くほどインパクトのパフォーマンスへの影響を持つことができることを学びました副作用がないことを保証することができます。

だから、これまで私の即時の反応はassert()内のコードを誘発する副作用は、最初の場所での主要なバグになるので、私は、次のマクロを作成し、私は通常assert()を使用することになり、絶対にどこでもそれを使用するべきであるということです。

// TODO: add handling of other compilers as appropriate. 
#if defined(__GNUC__) && defined(NDEBUG) 
    #define my_assert(condition) \ 
    if(!(condition)) __builtin_unreachable() 
#else 
    #define my_assert(condition) assert(condition) 
#endif 

基準の観点から、これはあなたが引数がassert()の標準的な動作であることから、このマクロを除外させる可能性がある、通常とNDEBUGビルド間の機能での分割を作成します。しかし、私のコードは、アサーションの失敗の場合でも、機能的には死んでしまうので、行動的な見地から完全に同等です。

だから私の質問です:誰もこれをしない理由を考えてもらえますか(多くの迂回を含むアサルトから)

質問する前に、はい、gccの動作が無効になることを確認しました。アサーションをNDEBUGビルドにキャストします。

+0

関連https://stackoverflow.com/a/40447259/817643 – StoryTeller

+0

私が知る限り、これをしない理由はありません。リリースビルドでは最適化のためのものを想定し、デバッグビルドのアサーションで置き換えてプログラミングエラーをキャッチします。 – StoryTeller

+1

デバッグアサーションには、しばしばデバッグモードでしか使用できない変数や呼び出しが含まれているため、「絶対にどこでも使用する」アプローチは実際には機能しません。より良いアイデアは、 'my_assume'のようなより適切な名前を持つ専用マクロを定義し、適切な場所でのみ使用することです。 – VTT

答えて

2

はい、使用しない理由があります。 一部の人々はアサートと例外(assert(x>0); if (!(x<0)) throw std::logic_error(".."))を組み合わせた以下の守備のコードの練習を使用する - この答えを参照してください:リリースビルドのため

Test Cases AND assertion statements

あなたのマクロが黙っ例外一部を壊します。

+2

私はプログラミングのエラーとランタイムエラーが混ざり合っているので、この練習が本当に好きではありません。その主張は、私の意見ではそこには存在しません。私のコードベースはこれに悩まされることはありませんが、これは心に留めておくのが良いことです。 – Frank

+2

そのtbhの値は表示されません。これは、 'assert()'の目的を、リリースコードにランタイムの影響がゼロであると捉えているようです。もしあなたが望むのであれば、例外を使うこともできます。 – Galik

+1

これは防御的ではありませんが、冗長なコードです。リリースビルドにチェックを入れる必要がある場合は、特別な、コンパイルされたリリースモードのrelease_assertを作成するか、または例外スローのみを使用します。アサート+スローは悪い習慣です。 – geza

関連する問題