|
From: John R.
|
Evan Lavelle wrote:
> uint8_t *cptr = (uint8_t *)&src;
> // **BODGE** fixes valgrind error messages: is there a better
> // way to do this?
> // if(Dbits == 128)
> // Dbits = 80;
> for(int i = 0; i < Dbits; i += 8) {
> mask = *cptr++; // <--- VALGRIND REPORTS ERROR HERE
> mask <<= i;
> *dst |= mask;
> }
Is that a true copy+paste of the source code, with no overriding of
operators, and an accurate transcription of the error location?
Does compilation deliver a closed subroutine or inlined code?
Does changing the compiler optimization level between -O2 and -O0
affect the location that memcheck reports?
Memcheck should not complain for the fetch:
mask = *cptr++;
because a fetch does not "use" the bits yet; but memcheck does remember
the status of the fetched bits (initialized or uninitialized.)
No system call [often a write()] and no conditional branch depends on
the bits yet.
Memcheck should not complain for the OR-to-memory:
*dst |= mask;
but instead "merely" update the accounting information about which bits
at *dst are now uninitialized:
A bit of *dst which previously was 1, keeps that initialized value.
( 1 OR x ) is 1.
A bit of *dst which previously was 0, but which lines up with an
uninitialized bit of mask, becomes uninitialized. ( 0 OR x ) is x.
A bit of *dst which previously was uninitialized, but which lines up
with an initialized 1 bit of mask, becomes 1. ( uninit OR 1 ) is 1.
A bit of *dst which previously was uninitialized, and which lines up
with an initialized 0 bit of mask, or with an uninitialized bit of
mask, remains uninitialized. Both ( uninit OR 0 ) and ( uninit OR uninit )
are uninit.
The uninitialized bits still do not affect any conditional branch,
nor any system call, so memcheck still should not complain yet.
> This code works, and doesn't depend on an uninitialised value, but
> Valgrind reports an error when 'T' is a long double.
The workaround for such cases is always the same:
memset(&src, 0, sizeof(src));
which obviously must be done before any existing use of src.
Unfortunately this may mean propagating the memset all the way
back to the allocation of src, which may be far away from the text
of TVLBigInt::mp_set_real().
--
|