|
From: Scott L. <sc...@sw...> - 2005-10-17 19:33:47
|
Valgrind 3.0.1 erroneously reports an error ("Conditional jump or move
depends on uninitialised value(s)") on the if-statements of both of the
following code snippets (compiled with GCC 3.2.3, no optimization):
int main()
{
int uninit;
int two = 2;
uninit *= two;
if(!(uninit & 1)) // there should be no error here
{
printf("Hello, world!\n");
}
return 0;
}
-----
int main()
{
int uninit;
uninit ^= uninit;
if(!(uninit & 1)) // there should be no error here
{
printf("Hello, world!\n");
}
return 0;
}
Scott
|
|
From: Julian S. <js...@ac...> - 2005-10-17 22:46:24
|
Sure. Nobody is claiming that memcheck gives 100.0% accurate
definedness tracking at all times. It would probably be possible
to introduce extra precision in definedness tracking to cover the
two cases you show. However, that more elaborate instrumentation
is slower, and so will slow down the 99.9% of programs which don't
exhibit these behaviours.
The real issue is, we have to draw a line somewhere between accuracy
of definedness tracking and the performance overhead. Where do you
want that line to be? What we have concentrated on is to make it
reasonably accurate for most run-of-the-mill integer code, and from
the feedback we get I think we do pretty well on the whole.
That said .. if the cases you show are real problems in real code,
and not just example test cases, then I am interested in investigating
further.
J
On Monday 17 October 2005 20:42, Scott Long wrote:
> Valgrind 3.0.1 erroneously reports an error ("Conditional jump or move
> depends on uninitialised value(s)") on the if-statements of both of the
> following code snippets (compiled with GCC 3.2.3, no optimization):
>
> int main()
> {
> int uninit;
> int two = 2;
>
> uninit *= two;
> if(!(uninit & 1)) // there should be no error here
> {
> printf("Hello, world!\n");
> }
> return 0;
> }
>
> -----
>
> int main()
> {
> int uninit;
>
> uninit ^= uninit;
> if(!(uninit & 1)) // there should be no error here
> {
> printf("Hello, world!\n");
> }
> return 0;
> }
>
>
> Scott
>
>
> -------------------------------------------------------
> This SF.Net email is sponsored by:
> Power Architecture Resource Center: Free content, downloads, discussions,
> and more. http://solutions.newsforge.com/ibmarch.tmpl
> _______________________________________________
> Valgrind-users mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-users
|
|
From: Igmar P. <mai...@jd...> - 2005-10-18 07:31:24
|
> int main()
> {
> int uninit;
uninit is undefined here.
> int two = 2;
>
> uninit *= two;
this is uninit = uninit * 2;
As far as I can tell, the whole of uninit is undefined, so is the result
of the multiplication.
> if(!(uninit & 1)) // there should be no error here
> {
uninit still contains random data. Why shouldn't it give errors ?
Regards,
Igmar
|
|
From: Tom H. <to...@co...> - 2005-10-18 07:44:11
|
In message <Pin...@jd...>
Igmar Palsenberg <mai...@jd...> wrote:
>> int main()
>> {
>> int uninit;
>
> uninit is undefined here.
>
>> int two = 2;
>>
>> uninit *= two;
>
> this is uninit = uninit * 2;
>
> As far as I can tell, the whole of uninit is undefined, so is the result
> of the multiplication.
>
>> if(!(uninit & 1)) // there should be no error here
>> {
>
> uninit still contains random data. Why shouldn't it give errors ?
He is only looking at the lowest bit and as he has doubled it that
bit is guaranteed to be zero and well defined.
Multiplying by two is after equivalent to a left shift by one and
such a shift is guaranteed to shift in a zero and hence make the
bottom bit well defined.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Dirk M. <dm...@gm...> - 2005-10-18 09:17:50
|
On Tuesday 18 October 2005 00:48, Julian Seward wrote: > That said .. if the cases you show are real problems in real code, > and not just example test cases, then I am interested in investigating > further. well, the xor testcase failure is interesting, because that is indeed a real bug (we used to do defined-ness tracking at bitlevel for xor, while we never did that for multiplies so far). Dirk |
|
From: Tom H. <to...@co...> - 2005-10-18 09:25:12
|
In message <200...@gm...>
Dirk Mueller <dm...@gm...> wrote:
> On Tuesday 18 October 2005 00:48, Julian Seward wrote:
>
>> That said .. if the cases you show are real problems in real code,
>> and not just example test cases, then I am interested in investigating
>> further.
>
> well, the xor testcase failure is interesting, because that is indeed a real
> bug (we used to do defined-ness tracking at bitlevel for xor, while we never
> did that for multiplies so far).
There is (or was) a special case for xor of a register with itself
which caused memcheck to consider the whole thing as defined because
compilers use that trick to generate zero.
Other than that I think xor just marks an output bit as defined if
both input bits are defined as the result of xor always depends on
both inputs.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Julian S. <js...@ac...> - 2005-10-18 09:59:23
|
> > well, the xor testcase failure is interesting, because that is indeed a > > real bug (we used to do defined-ness tracking at bitlevel for xor, while > > we never did that for multiplies so far). > > There is (or was) a special case for xor of a register with itself > which caused memcheck to consider the whole thing as defined because > compilers use that trick to generate zero. That case is still there for x86 and amd64. I suspect the reason why it doesn't work here is because program was compiled with no optimisation and so gcc is not emitting 'xorl %reg,%reg' but some other longer sequence which the case doesn't catch. It has friends too now: the MySQL folks discovered that gcc sometimes produces 'sbbl %reg,%reg' which gets the carry flag into %reg and doesn't depend on its previous value. So that is handled similarly. > Other than that I think xor just marks an output bit as defined if > both input bits are defined as the result of xor always depends on > both inputs. Yeh .. I can't think of a more accurate definedness rule which is correct, unfortunately. --- Something I should have mentioned earlier: a good introduction to the definedness analysis in memcheck is available at http://www.valgrind.org/docs/memcheck2005.pdf. J |
|
From: Igmar P. <mai...@jd...> - 2005-10-18 09:49:43
|
> > As far as I can tell, the whole of uninit is undefined, so is the result
> > of the multiplication.
> >
> >> if(!(uninit & 1)) // there should be no error here
> >> {
> >
> > uninit still contains random data. Why shouldn't it give errors ?
>
> He is only looking at the lowest bit and as he has doubled it that
> bit is guaranteed to be zero and well defined.
The rest of the bits aren't defined. Since you can't address anything less
then a byte, it should give errors on these kind of operations if you ask
me.
> Multiplying by two is after equivalent to a left shift by one and
> such a shift is guaranteed to shift in a zero and hence make the
> bottom bit well defined.
You still take at least 8 bits when doing the and operation. From a
theoretical point it makes sense and you're right. From a logical sense
(partial) garbage in equals garbage out :)
Regards,
Igmar
|
|
From: Tom H. <to...@co...> - 2005-10-18 10:08:13
|
In message <Pin...@jd...>
Igmar Palsenberg <mai...@jd...> wrote:
>> > As far as I can tell, the whole of uninit is undefined, so is the result
>> > of the multiplication.
>> >
>> >> if(!(uninit & 1)) // there should be no error here
>> >> {
>> >
>> > uninit still contains random data. Why shouldn't it give errors ?
>>
>> He is only looking at the lowest bit and as he has doubled it that
>> bit is guaranteed to be zero and well defined.
>
> The rest of the bits aren't defined. Since you can't address anything less
> then a byte, it should give errors on these kind of operations if you ask
> me.
He is testing the bottom bit so the result of the test is perfectly
well defined - one of valgrinds strengths is that it does bit level
tracking of defined values not byte level.
>> Multiplying by two is after equivalent to a left shift by one and
>> such a shift is guaranteed to shift in a zero and hence make the
>> bottom bit well defined.
>
> You still take at least 8 bits when doing the and operation. From a
> theoretical point it makes sense and you're right. From a logical sense
> (partial) garbage in equals garbage out :)
The process may and 8 bits or 32 bits or 64 bits but only one of them
affects the result of the operation.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Florian W. <fw...@de...> - 2005-10-18 11:42:52
|
* Tom Hughes: > He is testing the bottom bit so the result of the test is perfectly > well defined No it's not. The compiler may have performed some transformation which changes the bit pattern because it is undefined as far it is concerned. > - one of valgrinds strengths is that it does bit level tracking of > defined values not byte level. Sure, but the C compiler doesn't. It might make sense to fix valgrind's MUL implementaton, but this C code is a poor test case. |
|
From: Tom H. <to...@co...> - 2005-10-18 11:58:53
|
In message <87k...@mi...>
Florian Weimer <fw...@de...> wrote:
> * Tom Hughes:
>
>> He is testing the bottom bit so the result of the test is perfectly
>> well defined
>
> No it's not. The compiler may have performed some transformation
> which changes the bit pattern because it is undefined as far it is
> concerned.
>
>> - one of valgrinds strengths is that it does bit level tracking of
>> defined values not byte level.
>
> Sure, but the C compiler doesn't.
>
> It might make sense to fix valgrind's MUL implementaton, but this C
> code is a poor test case.
OK. Strictly speaking we need to see the assembly - valgrind after all
doesn't care about compilers or indeed how you generated your code. All
it cares about is the generated instruction stream.
Assuming that the compiler has generated the obvious instructions the
test is well defined (even if valgrind doesn't realise that).
You are right of course that the code is almost certainly not
standards conforming because it is performing an operation on an
undefined variable which probably puts it at least into implementation
defined territory if not nasal demons territory.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|