In short, this is the issue where a variable's value is used without the said variable having been assigned a value. At this point, it's likely that these contents are just whichever bytes were in that part of RAM which just got allocated. As a result, this can lead to unpredictable behavior whenever these contents are used or accessed.
When encountered, Memcheck will throw errors similar to these:
$ valgrind --read-var-info=yes --leak-check=full ./unval
==6822== Memcheck, a memory error detector
==6822== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6822== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==6822== Command: ./unval
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E87B83: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Use of uninitialised value of size 8
==6822== at 0x4E8476B: _itoa_word (_itoa.c:179)
==6822== by 0x4E8812C: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E84775: _itoa_word (_itoa.c:179)
==6822== by 0x4E8812C: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E881AF: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E87C59: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E8841A: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E87CAB: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822== Conditional jump or move depends on uninitialised value(s)
==6822== at 0x4E87CE2: vfprintf (vfprintf.c:1631)
==6822== by 0x4E8F898: printf (printf.c:33)
==6822== by 0x400541: main (unval.cpp:6)
==6822==
==6822==
==6822== HEAP SUMMARY:
==6822== in use at exit: 0 bytes in 0 blocks
==6822== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==6822==
==6822== All heap blocks were freed -- no leaks are possible
==6822==
==6822== For counts of detected and suppressed errors, rerun with: -v
==6822== Use --track-origins=yes to see where uninitialised values come from
==6822== ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 0 from 0)
This particular series of errors was caused by the following small bit of code:
#include <cstring>
#include <cstdio>
int main() {
int x;
printf ("x = %d\n", x);
return 0;
}
As we can see in the preceding code, we never initialize our variable, which would be set to just any random value. If one is lucky, it'll be set to zero, or an equally (hopefully) harmless value. This code shows just how any of our uninitialized variables enter into library code.
Whether or not the use of uninitialized variables is harmful is hard to say, and depends heavily on the type of variable and the affected code. It is, however, far easier to simply assign a safe, default value than it is to hunt down and debug mysterious issues which may be caused (at random) by an uninitialized variable.
For additional information on where an uninitialized variable originates, one can pass the -track-origins=yes flag to Memcheck. This will tell it to keep more information per variable, which will make the tracking down of this type of issue much easier.