|
From: Jeremy D. <jer...@fr...> - 2003-06-10 14:55:02
|
Hi
Here are some thoughts I had while debugging some C++ code involving
floating values. I don't know whether this has been dealt before, I
found nothing in this regard.
$pr -tn test.cxx
1 struct X { int a; };
2
3 struct Y { float a; };
4
5 struct Z { float a; short b; };
6
7 int main(int,char **)
8 {
9 X x1;
10 X x2(x1);
11
12 Y y1;
13 Y y2(y1);
14
15 Z z1;
16 Z z2(z1);
17
18 return 0;
19 }
$g++ -pedantic -W -Wall -ggdb3 test.cxx
$valgrind ./a.out
[...]
==12512==
==12512== Use of uninitialised value of size 4
==12512== at 0x80484CC: main (test.cxx:13)
==12512== by 0x402A114E: __libc_start_main (in /lib/libc-2.2.5.so)
==12512== by 0x8048400: (within /home/denise/work/valgrind/a.out)
==12512==
==12512== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0
from 0)
[...]
(One could notice that gcc did not complain about unused variables,
but that's another story.)
Lines 9-10 issue no message: according to valgrind's documentation, it
is correct (there's no "observable" effect; see memcheck 3.5.2).
The message is produced because of line 13: an uninitialized floating
value is involved, and triggers an alert during loading. Once again,
according to vg's doc, it is correct.
The problem is in lines 15-16: how comes that vg remains silent ?
A quick look at generated assembly shows:
29 .LM3:
30
31 movl -4(%ebp),%eax
32 movl %eax,-8(%ebp)
33 .LM4:
34
35 flds -12(%ebp)
36 fstps -16(%ebp)
37 .LM5:
38
39 movl -24(%ebp),%eax
40 movl -20(%ebp),%edx
41 movl %eax,-32(%ebp)
42 movl %edx,-28(%ebp)
Lines 31-32 do the work for line 10 of test.cxx; so do lines 36-36 for
line 13.
Lines 39-42 are the interesting ones: in that case, the compiler found
it better to copy Z data by the exclusive use of integer
instructions. Hence valgrind's silence.
This is, IMHO, a very undesirable behavior discontinuity. Wouldn't be
better to have valgrind complain about uninitialized floating values
in exactly the same way as with integer ones ?
-J-
|
|
From: Julian S. <js...@ac...> - 2003-06-11 22:13:46
|
> Lines 39-42 are the interesting ones: in that case, the compiler found > it better to copy Z data by the exclusive use of integer > instructions. Hence valgrind's silence. > > This is, IMHO, a very undesirable behavior discontinuity. Wouldn't be > better to have valgrind complain about uninitialized floating values > in exactly the same way as with integer ones ? Your observations are completely correct. But the problem is, how can we know merely by looking at the object code, whether what is being moved is (in some high level language) an int or a float? I don't know of any general solution to this. J |
|
From: Nicholas N. <nj...@ca...> - 2003-06-12 07:32:00
|
On Wed, 11 Jun 2003, Julian Seward wrote: > > > Lines 39-42 are the interesting ones: in that case, the compiler found > > it better to copy Z data by the exclusive use of integer > > instructions. Hence valgrind's silence. > > > > This is, IMHO, a very undesirable behavior discontinuity. Wouldn't be > > better to have valgrind complain about uninitialized floating values > > in exactly the same way as with integer ones ? > > Your observations are completely correct. But the problem is, how > can we know merely by looking at the object code, whether what is > being moved is (in some high level language) an int or a float? > I don't know of any general solution to this. Just to clarify something: I said in another thread that Valgrind only complains if an uninitialised variable is used in a condition, as a system call arg, or as a pointer. That's not true for uninitialised values in floating point registers; they're always checked. The reason is that uninitialised non-FP data is often copied around in memory and through the general purpose regs, but in practice FP data is hardly ever copied around uninitialised via the FP registers. And because of the way FP instructions are handled, it's easier to check FP values as soon as they're used. And if you copied an uninitialised integer through a FP register, Valgrind would complain. That explains the behaviour you get in your test program. N |
|
From: Jeremy D. <jer...@fr...> - 2003-06-12 08:23:51
|
Nicholas Nethercote wrote:
> Just to clarify something: I said in another thread that Valgrind only
> complains if an uninitialised variable is used in a condition, as a system
> call arg, or as a pointer. That's not true for uninitialised values in
> floating point registers; they're always checked.
I know of that: it is written in the documentation (3.5.2).
> The reason is that
> uninitialised non-FP data is often copied around in memory and through the
> general purpose regs, but in practice FP data is hardly ever copied around
> uninitialised via the FP registers.
I disagree: this is exactly what happens in my example (which comes out
of a real program)
> And because of the way FP
> instructions are handled, it's easier to check FP values as soon as
> they're used. And if you copied an uninitialised integer through a FP
> register, Valgrind would complain. That explains the behaviour you get in
> your test program.
>
All I say is that this behavior could be improved (*I* did not copy an
uninitialised integer through a FP register, *the compiler* did --
moreover, it's actually a FP value), by making it the same as for
integer instructions ("delayed" warning).
-J-
|
|
From: Jeremy D. <jer...@fr...> - 2003-06-23 13:58:17
|
Julian Seward wrote: >>This is, IMHO, a very undesirable behavior discontinuity. Wouldn't be >>better to have valgrind complain about uninitialized floating values >>in exactly the same way as with integer ones ? > > > Your observations are completely correct. But the problem is, how > can we know merely by looking at the object code, whether what is > being moved is (in some high level language) an int or a float? > I don't know of any general solution to this. > I don't know of any either ;-) Let's make it clear: my suggestion is to add the same instrumentation to *assembly* floating instructions (flds, fstps, ...) as the one already in use for integer instructions. In my example, I would not expect vg to issue a message at copy construction of y2; I'd like an alert to be triggered when y2's use gets problematic (i.e. never, here). This could be achieved through the same "delay" scheme used for integer instructions (i.e. when control flow relies on it or something). -J- |
|
From: Jeremy D. <jer...@fr...> - 2003-06-12 07:09:50
|
Julian Seward wrote: >>This is, IMHO, a very undesirable behavior discontinuity. Wouldn't be >>better to have valgrind complain about uninitialized floating values >>in exactly the same way as with integer ones ? > > > Your observations are completely correct. But the problem is, how > can we know merely by looking at the object code, whether what is > being moved is (in some high level language) an int or a float? > I don't know of any general solution to this. > I don't know of any either ;-) Let's make it clear: my suggestion is to add the same instrumentation to *assembly* floating instructions (flds, fstps, ...) as the one already in use for integer instructions. In my example, I would not expect vg to issue a message at copy construction of y2; I'd like an alert to be triggered when y2's use gets problematic (i.e. never, here). This could be achieved through the same "delay" scheme used for integer instructions (i.e. when control flow relies on it or something). -J- |