web-dev-qa-db-ja.com

初期化されていないメンバー変数を簡単に見つける方法

初期化されていないクラスメンバー変数を見つける簡単な方法を探しています。

実行時またはコンパイル時のいずれかでそれらを見つけることは問題ありません。

現在、クラスコンストラクターにブレークポイントがあり、メンバー変数を1つずつ調べます。

45
user254669

GCCを使用する場合は、-Weffc++フラグを使用できます。これは、メンバーの初期化リストで変数が初期化されていない場合に警告を生成します。この:

class Foo
{
  int v;
  Foo() {}
};

につながる:

$ g++ -c -Weffc++ foo.cpp -o foo.o
foo.cpp: In constructor ‘Foo::Foo()’:
foo.cpp:4: warning: ‘Foo::v’ should be initialized in the member initialization list

欠点の1つは、変数に適切なデフォルトコンストラクターがあり、初期化が必要ない場合に-Weffc++も警告することです。また、コンストラクターで変数を初期化するときに警告しますが、メンバー初期化リストでは警告しません。また、他の多くのC++スタイルの問題(コピーコンストラクターの欠落など)について警告するため、-Weffc++を定期的に使用する場合は、コードを少しクリーンアップする必要があります。

また、匿名ユニオンを使用すると常に警告が表示されるバグがありますが、現在は他の方法で回避できず、警告をオフにすることができます。

#pragma GCC diagnostic ignored "-Weffc++"

しかし全体的に、私は-Weffc++が多くの一般的なC++の間違いを見つけるのに信じられないほど有用であることを発見しました。

29
Grumbel

cppcheck はこれを見つけます、例えば:

cppcheck my_src_dir --output-file=check.txt --inconclusive --enable=warning
10
Johan Kotlinski

Valgrind は、Linuxを使用しているかどうかを示します。

10
Zitrax

Valgrind[〜#〜] free [〜#〜]、Linuxの場合)および Purify =(Windowsの場合)特別な仮想マシンでコードを実行して、初期化されていない変数、無効なポインターなどを見つけます。

これは使いやすく、非常に強力です。初期化されていない明らかな変数以外にも多くのバグが見つかる可能性があります。

CoverityKlocwork 、および Lint は、静的コード分析を使用して初期化されていない変数を見つけることができます。

10
Will

_-Wuninitialized_?

(これは、変数が初期化されずに使用されているかどうか、つまり

_struct Q { 
  int x, y;
  Q() : x(2) {}
  int get_xy() const { return x*y; }
};
_

g ++は、ユーザーがyに割り当てずにget_xy()を呼び出した場合にのみ警告します。

6
kennytm

Visual Studio(MSVC)には/ sdl(追加のセキュリティチェックを有効にする)コンパイラオプションがあります( http://msdn.Microsoft.com/en-us/library/jj161081.aspx )。実行時、それ:

クラスメンバーの初期化を実行します。オブジェクトのインスタンス化時に(コンストラクターの実行前に)ポインター型のクラスメンバーを自動的にゼロに初期化します。これは、コンストラクターが明示的に初期化しないクラスメンバーに関連付けられた未初期化データの使用を防ぐのに役立ちます。

これは、コンパイル時に初期化されていないメンバー変数を検出するのに役立ちませんが、実行時に発生した場合の動作をより予測可能にします。もちろん、このオプションが有効になっていることに依存するコードを書くべきではありません。

5
Quatari

Visual Studioを使用している場合は、デバッグモードでコンパイルし、デバッガーでプログラムを停止し、0xCC(スタック)または0xCD(ヒープ)を含むバイトに初期化される変数を探します。

個人的には、より徹底的なアプローチのために静的分析ツールに投資します。

4
Kaz Dragon

Visual Studioで/ analyze (「チームシステム」)

2
Terry Mahaffey

Clang-analyzeを使用したClangはこれを実行できます。イベントは、未使用の変数がいつアクセスされたかを示すNice HTMLレポートを作成します。

気をつけて!ここで提案されているコンパイラオプションは、信頼性もバージョン非依存でもありません。簡単な例を考えてみましょう。

_class A {
  int a;
public:
  void mA() {
    printf("haha");
    ++a;
    int g = 2/a;
    printf("%i\n",g);
  }
};

int main() {
  A a;
  a.mA();
}
_

_g++ -O3 -Weffc++ -Wuninitialized_でコンパイルすると、これは4.6までのgccバージョンでuninitializedを報告し、4.7および4.8(MacPortsでテスト済み)で問題なく通過します。その後、奇妙なことに、printf("haha");を削除すると、4.7と4.8の両方が突然_uninitialized A::a_になります。 Clangは少し便利です。これは、初期化されていない変数に(便利な_0_の代わりに)何らかの方法でごみを割り当てるためです。

上記の初期化されていない_A::a_をvalgrindで発見することもできませんでした。おそらく、valgrindを示唆する優しさは、このエラーを見つけるための適切なオプションを提供する可能性があります。

結論:素晴らしい質問です。現時点ではあまり信頼性の高いソリューションではありません...(私が見ているように)。

0
P Marecki