Should I worry about “Conditional jump or move depends on uninitialised value(s)”?

心已入冬 提交于 2019-12-19 03:44:05

问题


If you've used Memcheck (from Valgrind) you'll probably be familiar with this message...

Conditional jump or move depends on uninitialized value(s)

I've read about this and it simply occurs when you use an uninitialized value.

MyClass s;
s.DoStuff();

This will work because s is automatically initialized... So if this is the case, and it works, why does Memcheck tell me that it's uninitialized? Should the message be ignored?

Perhaps I misunderstood where the error was directing me. From the Valgrind manual, the actual erroneous snippet is...

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

However, in my code, I can't see anything like that. I have noticed however that the function at the top of the stack trace Memcheck shows me is a virtual function; could this be something to do with it?

==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)

Update 1:

I took a look at GlutApplication.cpp:120, and it looks like the uninitialized variable was being passed in to a function on that line. Simple!


回答1:


Can you post a more complete sample? It's hard to see how there would be that particular error with out some form of goto or flow changing statement.

I most commonly see this error in code like the following

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

This code is fundamentally incorrect. The reason why is that even though s2 has a constructor, it's not executed if someCondition is true. The goto statement will jump over the initialization and at the last line of the program s2 will be uninitialized and essentially point to garbage.

EDIT

You may also want to check out this page which gives hints on how to decipher this particular valgrind error

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

Addendum

Another common cause for this I've just found is when you pass over some integer constants to a variadic function, which are put on the stack as ints, but when the callee gets it as longs, you've got a problem on 64-bit machines.

I was almost about to give up and just consider valgrind being stupid, then I've realised that simply casting it to long fixes it.

So my upshot is: take this messages seriously.




回答2:


You can add the flag --track-origins=yes to valgrind and it will give you information on the sources of uninitialised data. It runs slower, but can be helpful.

Source: Valgrind User Manual




回答3:


If Valgrind states that a value is not initialised, then in 99.5% it is really not initialised. Normally, when compiler reports use of an uninitialised value (-Wuninitialized in GCC), you check for inline unrolls, as your uninitialised value can be declared (and not initialised) for example 10 levels of inline function "calls" (or template unrolls) higher, than actual GCC report. Valgrind does the same, but in runtime. So you should check whole path in which uninitialised value travelled from place of being declared (and not initialised), to the place where it's actually used. The path can be for example: cascade of function calls, where each function passes its arguments (and possibly uninitialised value) to next function. Valgrind will report in last function, when the value is actually used.

Generally you should not ignore what Valgrind states. Valgrind is not a simple trace program. It can be seen as a virtual machine:

Valgrind is in essence a virtual machine using just-in-time (JIT) compilation techniques, including dynamic recompilation. Nothing from the original program ever gets run directly on the host processor. Instead, Valgrind first translates the program into a temporary, simpler form called Intermediate Representation (IR), which is a processor-neutral, SSA-based form. After the conversion, a tool (see below) is free to do whatever transformations it would like on the IR, before Valgrind translates the IR back into machine code and lets the host processor run it. Even though it could use dynamic translation (that is, the host and target processors are from different architectures), it doesn't. Valgrind recompiles binary code to run on host and target (or simulated) CPUs of the same architecture. (Wikipedia)




回答4:


It would be very helpful if you can post more code, especially from the part where valgrind thinks the error is.

If this happens every time you instantiate the class, you probably forgot to initialize one of the members in the constructor.

And yes: You should worry about this error, those guys can really bite you.




回答5:


In 64-bits machine. Usually, int takes 4 bytes in memory. But long will take 8 bytes in memory. So simply refer an int value as long format will cause totally incorrect result. An convert is needed in this situation.




回答6:


The error does not seem to come from your code, but a library you are using.

Valgrind comes with some default error suppression, but that probably does not cover the library you are using.

The error-checking tools detect numerous problems in the base libraries, such as the GNU C library, and the X11 client libraries, which come pre-installed on your GNU/Linux system. You can't easily fix these, but you don't want to see these errors (and yes, there are many!) So Valgrind reads a list of errors to suppress at startup. A default suppression file is created by the ./configure script when the system is built.

You can create your own error suppressions that you know are irrelevant to your code.

See the similar SO question Why does Valgrind not like my usage of glutCreateWindow?



来源:https://stackoverflow.com/questions/765913/should-i-worry-about-conditional-jump-or-move-depends-on-uninitialised-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!