2012-07-01 7 views
18

の中でGCCがコードを削除しないようにするにはどうすればよいですか?(0)ブロック?gccで "if(0)"の除去を無効にする

if (0) 
    do_some_debug_printing_and_checking(); 
その後

、ブレークポイントがヒットしたとき、私はdo_some_debug_printing_and_checkingでクリックしてください()ライン:

私は、Visual Studioを使用して、私のデバッグ技術の一つは、私のプログラムでは、このようなコードを置くことです「次の文を設定」を選択して強制的に実行します。

バックエンドとしてgcc/gdbを使用すると、GCCは(0)文の場合、GCCが単にコードを内から削除するため、「set next statement」は機能しなくなります。

もちろん、-O0フラグを使用して最適化を無効にしています。また、-fno-dce -fno-tree-dceフラグをデッドコード除去を明示的に無効にするように試みましたが、効果はありません。 次の文を使用してジャンプすることはできません。

gccにの削除を無効にする方法はありますか?(0)の内容は?

編集:

  1. それはまだそれが勝ったコードの余分な行
  2. だ:「追加の変数」の回避策について

    おかげで、しかし、私はそれについて好きではない2つのことがあります私がリリース版をビルドするときに自動的に最適化されていて、それらのデバッグが消えてしまわないようにしてください。確かに私は#ifdef-sを使うことができますが、それはもっと余分な行です。

本当にGCCにデッドコードを保存させるオプションはありませんか?

+1

私は、これはあなたが求めていたものではありません知っているが、してみてくださいifにはグローバル変数をfalseに設定してください。そうすれば、コンパイラはif文を最適化しません。 –

+12

その機能を実行したいときにgdbで単に 'do_some_debug_printing_and_checking()'を呼び出さないのはなぜですか? – Mat

答えて

12

最も簡単なことは、外部リンケージを使用して変数に依存するかどうかを確認することです。

など。

extern bool debug; 
if (debug) 
    do_some_debug_printing_and_checking(); 

名前空間スコープでどこか:

bool debug = false; 
+5

私はそこに「揮発性」を落とします。 – Kos

+0

@Kos:なぜあなたはそれをしますか? –

+0

コンパイラは、変数の値がいくつかの2つの点の間で変更されていないとは仮定しません。 – Kos

8

私はこれを行うには、GCCコンパイラフラグに依存しないでしょう。コンパイラのフラグは、gccのバージョン間で変更され、コンパイラ間で変更されます。 Visual C++で6ヶ月で同じコードをデバッグする必要があるかもしれません。

@CharlesBaileyは、extern変数でこれを行う方法について良い提案をしています。変数全体がモジュール全体に公開されたり、静的ストレージに保存されたりする必要がない代替方法があります。

if文の範囲で一時変数volatileを宣言します。

if (volatile bool dbg = false) 
{ 
    do_some_debug_printing_and_checking(); 
} 

これは非常に狭い一時変数のスコープを保持します。 volatile修飾子は、コンパイラが変数について何も想定しないようにしたり、分岐を最適化したりしません。

変数は常にスタックに割り当てられ、関数が終了するまでスタックに保持されます。このアプローチとexternアプローチの両方が機能するはずですが、若干異なる(おそらく無視できる)トレードオフがあります。

あなたはこの問題を解決するためのマクロを使用するために喜んでいる場合は、あなたのリリースで、あなたのコードは、あなたが簡単に生産に一時変数を無効にすることができます

#ifndef IS_DEBUGGING 
# define IS_DEBUGGING 0 
#endif 

#if IS_DEBUGGING 
# define TMP_DBG_FLAG volatile bool dbg_flag = false 
#else 
# define TMP_DBG_FLAG false 
#endif 

次にとしてあなたifステートメントを宣言します。

if (TMP_DBG_FLAG) 
{ 
    do_some_debug_printing_and_checking(); 
} 

IS_DEBUGGINGを1に定義すると、ローカル変数が作成され、volatile宣言され、保持されます。 IS_DEBUGGINGを0に定義すると、マクロは定数falseに展開され、コンパイラは分岐を最適化します。非常に似たようなことがexternのアプローチでも実行できます。

このコードは余分な行数ではありませんが、TMP_DBG_FLAGを使用する回数とは関係ありません。コードはifdefのトンを使用するよりも読みやすくなります。マクロは、(それに__LINE__の値を追加することで)少し安全作ることができるが、これは3つのマクロが必要になり、おそらく必要はありません。

#if IS_DEBUGGING 
// paste symbols 'x' and 'y' together 
# define TMP_DBG_FLAG_SYMCAT0(x,y) x ## y 

// need one level of indirection to expand __LINE__... 
# define TMP_DBG_FLAG_SYMCAT(x,y) TMP_DBG_FLAG_SYMCAT0(x,y) 

# define TMP_DBG_FLAG volatile bool TMP_DBG_FLAG_SYMCAT(dbg_flag_,__LINE__) = false 
#else 
# define TMP_DBG_FLAG false 
#endif