4

Memcheck (Valgrind から) を使用したことがある場合は、おそらくこのメッセージに精通しているでしょう...

条件付きジャンプまたは移動は、初期化されていない値に依存します

これについて読んだことがありますが、初期化されていない値を使用すると発生します。

MyClass s;
s.DoStuff();

は自動的に初期化されるため、これsは機能します...これが事実であり、機能する場合、Memcheck はなぜ初期化されていないと通知するのでしょうか? メッセージを無視する必要がありますか?

おそらく、エラーがどこに向けられているのかを誤解していたのでしょう。Valgrindマニュアルから、実際の誤ったスニペットは...

int main()
{
  int x;
  printf ("x = %d\n", x);
}

ただし、私のコードでは、そのようなものは見られません。ただし、Memcheck が示すスタック トレースの先頭にある関数が仮想関数であることに気付きました。これは何か関係があるのでしょうか?

==14446== Conditional jump or move depends on uninitialised value(s)
==14446==    at 0x414164: vimrid::glut::GlutApplication::FinishRender() (GlutApplication.cpp:120)
==14446==    by 0x422434: vimrid::demos::filterdemos::FilterDemo3::Render() (FilterDemo3.cpp:260)
==14446==    by 0x412D3D: vimrid::VimridApplication::UpdateAndRender() (VimridApplication.cpp:93)
==14446==    by 0x4144BA: vimrid::glut::GlutApplication::glutHandleDisplay() (GlutApplication.cpp:201)
==14446==    by 0x41486A: vimrid::glut::GlutApplication::glutCallbackDisplay() (GlutApplication.cpp:277)
==14446==    by 0x54D9FAA: (within /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x54DDA4A: fgEnumWindows (in /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x54DA4A3: glutMainLoopEvent (in /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x54DAEB5: glutMainLoop (in /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x413FF8: vimrid::glut::GlutApplication::Run() (GlutApplication.cpp:112)
==14446==    by 0x41249D: vimrid::Launcher::runDemo(vimrid::VimridSettings&) (Launcher.cpp:150)
==14446==    by 0x412767: vimrid::Launcher::Launch(int, char**) (Launcher.cpp:62)

更新 1:

GlutApplication.cpp:120 を調べたところ、初期化されていない変数がその行の関数に渡されていたようです。単純!

4

6 に答える 6

17

フラグ--track-origins=yesを valgrind に追加すると、初期化されていないデータのソースに関する情報が得られます。実行速度は遅くなりますが、役立つ場合があります。

出典: Valgrind ユーザーマニュアル

于 2011-04-15T18:19:54.823 に答える
6

より完全なサンプルを投稿できますか? なんらかの形式の goto またはフロー変更ステートメントがなければ、その特定のエラーがどのように発生するかを理解するのは困難です。

このエラーは、次のようなコードでよく見られます

MyClass s1;
...
if ( someCondition ) { 
  goto Foo:
}
MyClass s2;
Foo:
cout << s2.GetName();

このコードは根本的に間違っています。その理由は、s2 にはコンストラクターがあっても、someCondition が true の場合は実行されないためです。goto ステートメントは初期化を飛び越え、プログラムの最後の行で s2 は初期化されず、本質的にガベージを指します。

編集

この特定の valgrind エラーを解読する方法に関するヒントを提供するこのページもチェックしてください。

https://computing.llnl.gov/code/memcheck/#deciphering4

補遺

私が見つけたもう 1 つの一般的な原因は、いくつかの整数定数を int としてスタックに置かれる variadic 関数に渡すときですが、呼び出し先が long としてそれを取得すると、64- で問題が発生します。ビットマシン。

私はほとんどあきらめようとしていて、valgrind はばかげていると考えていました。

つまり、このメッセージを真剣に受け止めてください。

于 2009-04-19T19:13:20.907 に答える
3

Valgrind が値が初期化されていないと述べている場合、99.5% では実際には初期化されていません。通常、コンパイラが初期化されていない値の使用を報告する場合 (GCC では -Wuninitialized)、たとえば 10 レベルのインライン関数「呼び出し」(またはテンプレートの展開) など、初期化されていない値を宣言できる (初期化されない) ため、インラインの展開をチェックします。実際の G​​CC レポートよりも高くなります。Valgrind も同じことを行いますが、実行時に. したがって、初期化されていない値が宣言された(初期化されていない)場所から実際に使用される場所まで移動したパス全体を確認する必要があります。パスは、たとえば次のようになります。関数呼び出しのカスケード。各関数はその引数 (および場合によっては初期化されていない値) を次の関数に渡します。値が実際に使用されると、Valgrind は最後の関数で報告します。

一般に、Valgrind が述べていることを無視してはなりません。Valgrind は単純なトレース プログラムではありません。これは仮想マシンとして見ることができます:

Valgrind は本質的に、動的再コンパイルを含むジャストインタイム (JIT) コンパイル手法を使用する仮想マシンです。元のプログラムの何もホスト プロセッサで直接実行されることはありません。代わりに、Valgrind は最初にプログラムを中間表現 (IR) と呼ばれる一時的で単純な形式に変換します。これはプロセッサに依存しない SSA ベースの形式です。変換後、Valgrind が IR をマシン コードに変換してホスト プロセッサに実行させる前に、ツール (以下を参照) は IR で必要な変換を自由に行うことができます。動的変換を使用できますが (つまり、ホスト プロセッサとターゲット プロセッサが異なるアーキテクチャからのもの)、使用しません。Valgrind はバイナリ コードを再コンパイルして、同じアーキテクチャのホストおよびターゲット (またはシミュレートされた) CPU で実行します。

于 2009-04-19T21:17:06.943 に答える
1

64 ビット マシンで。通常、int はメモリ内で 4 バイトを使用します。ただし、 long はメモリ内で 8 バイトを使用します。そのため、単純に int 値を参照すると、長い形式ではまったく正しくない結果が生じます。この状況では変換が必要です。

于 2012-04-30T18:04:53.537 に答える
-1

エラーはコードからではなく、使用しているライブラリから発生しているようです。

Valgrind にはいくつかのデフォルトのエラー抑制が付属していますが、使用しているライブラリはおそらくカバーされていません。

エラー チェック ツールは、GNU C ライブラリや、GNU/Linux システムにプリインストールされている X11 クライアント ライブラリなどの基本ライブラリの多数の問題を検出します。これらを簡単に修正することはできませんが、これらのエラーを見たくはありません (もちろん、たくさんあります!)。そのため、Valgrind は起動時に抑制するエラーのリストを読み取ります。デフォルトの抑制ファイルは、システムの構築時に ./configure スクリプトによって作成されます。

コードとは無関係であることがわかっている独自のエラー抑制を作成できます。

同様の SO の質問を参照してください

于 2009-04-20T03:03:40.790 に答える