初期化されていないクラスメンバー変数を見つける簡単な方法を探しています。
実行時またはコンパイル時のいずれかでそれらを見つけることは問題ありません。
現在、クラスコンストラクターにブレークポイントがあり、メンバー変数を1つずつ調べます。
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++の間違いを見つけるのに信じられないほど有用であることを発見しました。
cppcheck はこれを見つけます、例えば:
cppcheck my_src_dir --output-file=check.txt --inconclusive --enable=warning
Valgrind は、Linuxを使用しているかどうかを示します。
_-Wuninitialized
_?
(これは、変数が初期化されずに使用されているかどうか、つまり
_struct Q {
int x, y;
Q() : x(2) {}
int get_xy() const { return x*y; }
};
_
g ++は、ユーザーがy
に割り当てずにget_xy()
を呼び出した場合にのみ警告します。
Visual Studio(MSVC)には/ sdl(追加のセキュリティチェックを有効にする)コンパイラオプションがあります( http://msdn.Microsoft.com/en-us/library/jj161081.aspx )。実行時、それ:
クラスメンバーの初期化を実行します。オブジェクトのインスタンス化時に(コンストラクターの実行前に)ポインター型のクラスメンバーを自動的にゼロに初期化します。これは、コンストラクターが明示的に初期化しないクラスメンバーに関連付けられた未初期化データの使用を防ぐのに役立ちます。
これは、コンパイル時に初期化されていないメンバー変数を検出するのに役立ちませんが、実行時に発生した場合の動作をより予測可能にします。もちろん、このオプションが有効になっていることに依存するコードを書くべきではありません。
Visual Studioを使用している場合は、デバッグモードでコンパイルし、デバッガーでプログラムを停止し、0xCC(スタック)または0xCD(ヒープ)を含むバイトに初期化される変数を探します。
個人的には、より徹底的なアプローチのために静的分析ツールに投資します。
Visual Studioで/ analyze (「チームシステム」)
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
を示唆する優しさは、このエラーを見つけるための適切なオプションを提供する可能性があります。
結論:素晴らしい質問です。現時点ではあまり信頼性の高いソリューションではありません...(私が見ているように)。