tags 251815 - moreinfo
found 251815 1:3.7.0-6
thanks

On Fri, May 11, 2012 at 04:01:37PM +0200, Alessandro Ghedini wrote:
> > ==17712== Conditional jump or move depends on uninitialised value(s)
> > 
> > I was getting such a message.  But when I looked at it closely it 
> > appears that the value isn't actually unintialized.  What happened was 
> > two values - one known to be 0 and another uninitialized - were 
> > multiplied together to give this value that valgrind thinks is 
> > unitialized.  Of course zero times an unitialized (in this case, 
> > integer) value is always 0.  So this warning is spurious on Valgrind's 
> > part.

I'm very dubious as to whether "fixing" this would be an improvement.

At the C level, it's undefined behaviour.  While you might think you'll
get 0 out, the optimisers can take advantage of knowing it's undefined
and give a different answer.  That warning from valgrind really is something
you should be fixing in your code.

The reason why valgrind generally only reports when undefined values actually
affect control flow or get passed to a syscall is because of hand-written
assembler and optimised compiler output which do things like copy undefined
values around.  That isn't the case here - this is C code doing things which
are undefined in C.

I've not managed to get this particular case to give a result other than
zero (it seems that currently "multiplication by zero" gets optimised before
taking advantage of the undefined value), but this example shows the sort
of optimisations that I'm talking about:

$ cat x.c
int f(int y) {
    int x;
    return y < 0 ? 42 : x + y;
}
$ gcc -O2 -S -o- x.c
    .file   "x.c"
    .text
    .p2align 4,,15
    .globl  f
    .type   f, @function
f:
.LFB0:
    .cfi_startproc
    movl    $42, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   f, .-f
    .ident  "GCC: (Debian 4.7.2-4) 4.7.2"
    .section    .note.GNU-stack,"",@progbits

So the compiler has taken advantage of the result of computing x+y being
undefined behaviour and optimised the function to effectively just:

int f(int y) { return 42; }

And that's totally valid - if y is negative, then 42 is the right answer.
If y isn't negative, the program is permitted to do anything, and that
includes returning 42 from f.

> Does this still happen with the sid version of valgrind? If so, it would be
> much more helpful if you could provide a snippet of code that reproduces the
> problem, instead of describing it in English :)

Testcase attached.  With valgrind 1:3.7.0-6 and gcc 4:4.7.2-1 on amd64:

$ gcc -Wall -W -g vg-zero-mul.c
vg-zero-mul.c: In function ‘main’:
vg-zero-mul.c:5:11: warning: ‘x’ is used uninitialized in this function 
[-Wuninitialized]
$ valgrind ./a.out
==10770== Memcheck, a memory error detector
==10770== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==10770== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==10770== Command: ./a.out
==10770== 
==10770== Use of uninitialised value of size 8
==10770==    at 0x4E70FCB: _itoa_word (_itoa.c:195)
==10770==    by 0x4E72FA6: vfprintf (vfprintf.c:1622)
==10770==    by 0x4E7C279: printf (printf.c:35)
==10770==    by 0x400532: main (vg-zero-mul.c:5)
==10770== 
==10770== Conditional jump or move depends on uninitialised value(s)
==10770==    at 0x4E70FD5: _itoa_word (_itoa.c:195)
==10770==    by 0x4E72FA6: vfprintf (vfprintf.c:1622)
==10770==    by 0x4E7C279: printf (printf.c:35)
==10770==    by 0x400532: main (vg-zero-mul.c:5)
==10770== 
==10770== Conditional jump or move depends on uninitialised value(s)
==10770==    at 0x4E730BA: vfprintf (vfprintf.c:1622)
==10770==    by 0x4E7C279: printf (printf.c:35)
==10770==    by 0x400532: main (vg-zero-mul.c:5)
==10770== 
==10770== Conditional jump or move depends on uninitialised value(s)
==10770==    at 0x4E730D8: vfprintf (vfprintf.c:1622)
==10770==    by 0x4E7C279: printf (printf.c:35)
==10770==    by 0x400532: main (vg-zero-mul.c:5)
==10770== 
0
==10770== 
==10770== HEAP SUMMARY:
==10770==     in use at exit: 0 bytes in 0 blocks
==10770==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==10770== 
==10770== All heap blocks were freed -- no leaks are possible
==10770== 
==10770== For counts of detected and suppressed errors, rerun with: -v
==10770== Use --track-origins=yes to see where uninitialised values come from
==10770== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 4 from 4)

And much the same if you compile with clang instead.

I think that "wontfix" is the appropriate response though.

Cheers,
    Olly
#include <stdio.h>
int main() {
    int x;
    int y = 0;
    printf("%d", x * y);
    return 0;
}

Attachment: signature.asc
Description: Digital signature

Reply via email to