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)