LWN.net Logo

Removing uninitialized_var()

Removing uninitialized_var()

Posted Dec 20, 2012 15:03 UTC (Thu) by nix (subscriber, #2304)
In reply to: Removing uninitialized_var() by michaeljt
Parent article: Removing uninitialized_var()

It can, of course, never be right in all circumstances (that would require a solution to the halting problem). It can sometimes be sure, and says as much ('is used uninitialized'). Often, it's not sure. What's odious is that there are lots of apparently simple cases that GCC can't yet handle, e.g.

if (foo)
/* initialize a */

/* later */

if (foo) /* value not affected by code above */
/* use a */

is a particularly notorious case.


(Log in to post comments)

Removing uninitialized_var()

Posted Dec 20, 2012 19:38 UTC (Thu) by zlynx (subscriber, #2285) [Link]

I recently read something discussing common threading pitfalls and code similar to yours came up.

It is kind of amazing how many non-intuitive optimizations can be made on code like that.

For example, it might be rewritten to something like:

initialize a
do stuff
use a
if (!foo)
undo using a

or rewritten into two function blocks, one for if (foo) and one for if (!foo).

or the initialization of a might be moved down into the other if (foo) block.

So anyway, it is entirely possible that after GCC swizzles the code around it cannot tell anymore. It might have actually used a without even looking at foo, intending to undo it later.

Removing uninitialized_var()

Posted Dec 28, 2012 20:38 UTC (Fri) by stevenb (guest, #11536) [Link]

That case is handled just fine, at least AFAICT:

$ cat t.c
extern int foo_p (int *, int);
extern int foo (int, int);
extern void bar (void);

int foo_p (int *x, int y)
{
int a;
if (*x) a = y;
bar ();
if (*x) return a;
bar ();
return -1;
}

int foo (int x, int y)
{
int a;
if (x) a = y;
bar ();
if (x) return a;
bar ();
return -1;
}
$
$ gcc-4.4 -S -O2 -W -Wall -Wextra t.c
t.c: In function ‘foo_p’:
t.c:7: warning: ‘a’ may be used uninitialized in this function
$
$ gcc-4.6 -S -O2 -W -Wall -Wextra t.c
t.c: In function ‘foo_p’:
t.c:7:7: warning: ‘a’ may be used uninitialized in this function [-Wuninitialized]
$
$ ./xgcc -B. -S -O2 -W -Wall -Wextra t.c --version
xgcc (GCC) 4.8.0 20121226 (experimental) [trunk revision 194725]
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./xgcc -B. -S -O2 -W -Wall -Wextra t.c
t.c: In function 'foo_p':
t.c:7:7: warning: 'a' may be used uninitialized in this function [-Wmaybe-uninitialized]
int a;
^
$

In foo_p, the compiler cannot know whether bar will change the value at *x and the warning is valid. In foo, which is your example, there is no warning. In general, there will be no warning if the compiler can prove that the code in your "/* later */" doesn't change the result of the tested conditional. This is implemented in tree-ssa-uninit.c.

Still, it's true that there will be false positives, or missed warnings. Proving whether a variable is used uninitialized is not an easy problem.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds