|
From: Jason V. D. <jas...@gm...> - 2017-12-20 15:37:16
|
Good day -
Please could anyone explain why valgrind v3.13.0, built for x86_64 under Linux
(RHEL 7.4), is complaining about
"Conditional jump or move depends on uninitialised value(s)"
in this case - I cannot see how any memory accessed by this
code is uninitialized, and inspecting the V bits and shadow
registers also does not show any 0 bits - the program always
stops with the above error, at the line
==26770== Thread 4:
==26770== Conditional jump or move depends on uninitialised value(s)
==26770== at 0x5C3EF46: lround (s_llround.c:42)
which is entered via the line in our code:
const uint32_t delta_time = uint32_t(std::lround(sensor.time * 2e9));
^^^^^^^^^^^^^^^^^^^^^^^^
This is a call to GLIBC v2.17's lround, in glibc source code file:
sysdeps/ieee754/dbl-64/wordsize-64/s_llround.c,
@ line 28:
long long int
__llround (double x)
{ // I recompiled glibc to add initializers for
// these auto variables, but it made no difference:
int32_t j0=0;
int64_t i0=0;
long long int result=0;
int sign=0;
EXTRACT_WORDS64 (i0, x);
j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
sign = i0 < 0 ? -1 : 1;
i0 &= UINT64_C(0xfffffffffffff);
i0 |= UINT64_C(0x10000000000000);
@ line 42:
==> if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
{
EXTRACT_WORDS64 resolves to an asm statement defined in
sysdeps/x86_64/fpu/math_private.h:
/* Direct movement of float into integer register. */
#define EXTRACT_WORDS64(i, d) \
do { \
int64_t i_; \
asm (MOVD " %1, %0" : "=rm" (i_) : "x" ((double) (d))); \
(i) = i_; \
} while (0)
.
When I run valgrind with options:
--tool=memcheck --track-origins=yes --vgdb-shadow-registers=yes
--vgdb=yes \
--vgdb-error=0 my_program ....
it invariably stops at the same s_llround.c:42 place shown above .
Inspecting the valid bits for both 'j0' (in glibc's __llround) and 'sensor.time'
(in our code) in GDB shows ALL VALID BITS set :
(gdb is stopped at s_llround.c, line 42):
(gdb) p &j0
Address requested for identifier "j0" which is in register $rdx
(gdb) p/x $rdxs1
$1 = 0xffffffff
(gdb) p j0
$1 = 6
// so the j0 variable appears to be valid, according to valgrind's
shadow register V-bits.
// So why did valgrind stop at that particular line, where no variable
or memory other
// than j0 is being accessed ?
(gdb) up
... ( back to our code: delta_time =
uint32_t(std::lround(sensor.time * 2e9));
... sensor is a structure reference variable
... )
(gdb) p &sensor->time
$16 = (double *) 0x10ea9088
(gdb) mo xb 0x10ea9088 8
ff ff ff ff ff ff ff ff
0x10EA9088: 0xef 0xd9 0x0e 0x32 0x57 0x0e 0x6a 0x3e
So how can I tell which valid bit valgrind is complaining about being 0 here ?
No relevant valid bits appear to be 0 ?
Yes, not all bits for the whole 40 byte 'sensor' structure are valid
yet (it is in the processof being constructed here) but the 8 bytes
referenced by 'sensor.time' ARE VALID , and no other bits can be
accessed by the statement at which valgrind stops.
It just says at the end:
==26770== Uninitialised value was created by a stack allocation
==26770== at 0x4E2979: main (Main.cpp:88)
Yes, the 'sensor' structure is part of a 200MB array created at
program initialization , which is populated by SPI + GPIO + DMA reads
from an embedded device, in the multi-threaded program. But the memory
being accessed by the statement above HAS ALL VALID BITS SET, so I
cannot see what valgrind is complaining about here .
I'd really appreciate some kind of '--show-valid-bits-and-addresses'
option to valgrind, which would make it display exactly the valid bits
it found to be 0, and which memory addresses / registers they
correspond to .
I believe the above behavior represents a BUG in latest version of
valgrind, because
NO RELEVANT VALID BITS ARE ZERO , AFAICS.
valgrind-3.12.0 (the RHEL-7.4 default version) displays the same behavior , and
stops at the same place with the same error.
I'd really like to test our program with valgrind, but false positives such as
the above are blocking this - I am having to abandon valgrind testing because of
this issue , because valgrind appears to be too buggy to use. The program runs
fine outside of valgrind without any errors (usually) - but as I am changing it
I'd like to run it under valgrind as part of standard automated testing.
Any ideas / suggestions how to resolve this false positive, or proof that it is
not a false positive, would be most gratefully received.
Thanks in advance & Best Regards .
Jason Vas Dias
|
|
From: Philippe W. <phi...@sk...> - 2017-12-20 19:42:40
|
Does it help to run with
--expensive-definedness-checks=yes
?
You might also try 3.14 GIT version, as some work was recently done
in the area of definedness checking and the above option was also
extended with a 3rd value (auto), which is less expensive.
Philippe
On Wed, 2017-12-20 at 15:37 +0000, Jason Vas Dias wrote:
> Good day -
>
> Please could anyone explain why valgrind v3.13.0, built for x86_64 under Linux
> (RHEL 7.4), is complaining about
> "Conditional jump or move depends on uninitialised value(s)"
> in this case - I cannot see how any memory accessed by this
> code is uninitialized, and inspecting the V bits and shadow
> registers also does not show any 0 bits - the program always
> stops with the above error, at the line
>
> ==26770== Thread 4:
> ==26770== Conditional jump or move depends on uninitialised value(s)
> ==26770== at 0x5C3EF46: lround (s_llround.c:42)
>
> which is entered via the line in our code:
>
> const uint32_t delta_time = uint32_t(std::lround(sensor.time * 2e9));
>
> ^^^^^^^^^^^^^^^^^^^^^^^^
> This is a call to GLIBC v2.17's lround, in glibc source code file:
> sysdeps/ieee754/dbl-64/wordsize-64/s_llround.c,
> @ line 28:
> long long int
> __llround (double x)
> { // I recompiled glibc to add initializers for
> // these auto variables, but it made no difference:
> int32_t j0=0;
> int64_t i0=0;
> long long int result=0;
> int sign=0;
>
> EXTRACT_WORDS64 (i0, x);
> j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
> sign = i0 < 0 ? -1 : 1;
> i0 &= UINT64_C(0xfffffffffffff);
> i0 |= UINT64_C(0x10000000000000);
> @ line 42:
> ==> if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
> {
>
> EXTRACT_WORDS64 resolves to an asm statement defined in
> sysdeps/x86_64/fpu/math_private.h:
> /* Direct movement of float into integer register. */
> #define EXTRACT_WORDS64(i, d) \
> do { \
> int64_t i_; \
> asm (MOVD " %1, %0" : "=rm" (i_) : "x" ((double) (d))); \
> (i) = i_; \
> } while (0)
>
> .
>
> When I run valgrind with options:
>
> --tool=memcheck --track-origins=yes --vgdb-shadow-registers=yes
> --vgdb=yes \
> --vgdb-error=0 my_program ....
>
> it invariably stops at the same s_llround.c:42 place shown above .
>
> Inspecting the valid bits for both 'j0' (in glibc's __llround) and 'sensor.time'
> (in our code) in GDB shows ALL VALID BITS set :
>
> (gdb is stopped at s_llround.c, line 42):
>
> (gdb) p &j0
> Address requested for identifier "j0" which is in register $rdx
> (gdb) p/x $rdxs1
> $1 = 0xffffffff
> (gdb) p j0
> $1 = 6
>
> // so the j0 variable appears to be valid, according to valgrind's
> shadow register V-bits.
> // So why did valgrind stop at that particular line, where no variable
> or memory other
> // than j0 is being accessed ?
>
> (gdb) up
> ... ( back to our code: delta_time =
> uint32_t(std::lround(sensor.time * 2e9));
> ... sensor is a structure reference variable
> ... )
>
> (gdb) p &sensor->time
> $16 = (double *) 0x10ea9088
> (gdb) mo xb 0x10ea9088 8
> ff ff ff ff ff ff ff ff
> 0x10EA9088: 0xef 0xd9 0x0e 0x32 0x57 0x0e 0x6a 0x3e
>
> So how can I tell which valid bit valgrind is complaining about being 0 here ?
> No relevant valid bits appear to be 0 ?
>
> Yes, not all bits for the whole 40 byte 'sensor' structure are valid
> yet (it is in the processof being constructed here) but the 8 bytes
> referenced by 'sensor.time' ARE VALID , and no other bits can be
> accessed by the statement at which valgrind stops.
>
> It just says at the end:
> ==26770== Uninitialised value was created by a stack allocation
> ==26770== at 0x4E2979: main (Main.cpp:88)
>
> Yes, the 'sensor' structure is part of a 200MB array created at
> program initialization , which is populated by SPI + GPIO + DMA reads
> from an embedded device, in the multi-threaded program. But the memory
> being accessed by the statement above HAS ALL VALID BITS SET, so I
> cannot see what valgrind is complaining about here .
>
> I'd really appreciate some kind of '--show-valid-bits-and-addresses'
> option to valgrind, which would make it display exactly the valid bits
> it found to be 0, and which memory addresses / registers they
> correspond to .
>
> I believe the above behavior represents a BUG in latest version of
> valgrind, because
> NO RELEVANT VALID BITS ARE ZERO , AFAICS.
>
> valgrind-3.12.0 (the RHEL-7.4 default version) displays the same behavior , and
> stops at the same place with the same error.
>
> I'd really like to test our program with valgrind, but false positives such as
> the above are blocking this - I am having to abandon valgrind testing because of
> this issue , because valgrind appears to be too buggy to use. The program runs
> fine outside of valgrind without any errors (usually) - but as I am changing it
> I'd like to run it under valgrind as part of standard automated testing.
>
> Any ideas / suggestions how to resolve this false positive, or proof that it is
> not a false positive, would be most gratefully received.
>
> Thanks in advance & Best Regards .
> Jason Vas Dias
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Valgrind-users mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-users
|