User: Password:
|
|
Subscribe / Log in / New account

Removing uninitialized_var()

Removing uninitialized_var()

Posted Dec 20, 2012 12:11 UTC (Thu) by michaeljt (subscriber, #39183)
Parent article: Removing uninitialized_var()

I wonder whether it is quite fair to the gcc people to call this a "compiler [bug] (*stupid* gcc behavior)"? Not that I know very much about compiler internals, but instinctively I wouldn't expect getting this sort of warning right to be an entirely trivial task.


(Log in to post comments)

Removing uninitialized_var()

Posted Dec 20, 2012 14:48 UTC (Thu) by kpfleming (subscriber, #23250) [Link]

The primarily complication is that developers (and users) use widely varying versions of GCC. Over time, of course, GCC gets better and better at avoiding false warnings, and developers tend to use the latest-and-greatest version on their systems. Users, though, like to stick with long-term-support distributions that have older compiler versions (some still using GCC 4.3.x), but also want their software to build without warnings. When the user reports a bug about a compiler warning, the developer frequently responds that it doesn't happen with the latest GCC, and wants to close it.

Solving the user's problem ends up requiring ugly workarounds that change the code (typically in non-functional ways) just to silence compiler warnings. Given that, it's quite reasonable to classify a compiler warning that is generated from code that cannot be trusted to have exhaustive proof of the potential failure as a 'bug' in the compiler.

Removing uninitialized_var()

Posted Dec 20, 2012 15:03 UTC (Thu) by nix (subscriber, #2304) [Link]

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.

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.

Removing uninitialized_var()

Posted Jan 4, 2013 10:16 UTC (Fri) by mlopezibanez (guest, #66088) [Link]

There is indeed a limit to what GCC can guess correctly, but there are also quite a number of bugs and deficiencies in the warning machinery. See http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings for a list of problems (the page may be slightly outdated by now) and http://gcc.gnu.org/PR24639 Solving these problems would require substantial work. Unfortunately, there is no enough people working on GCC to even start such work in the near future.

I wonder if kernel devs would be less frustrated with gcc if they tried to fix GCC bugs rather than work-around them. Well, perhaps they will become even more frustrated. ;-)

Removing uninitialized_var()

Posted Jan 4, 2013 12:05 UTC (Fri) by heijo (guest, #88363) [Link]

Removing uninitialized_var()

Posted Jan 4, 2013 23:24 UTC (Fri) by nix (subscriber, #2304) [Link]

It's impossible to get it right *in the general case*. You can get it right in an arbitrarily large percentage of special cases (and indeed, GCC often does, when it says 'is used uninitialized' rather than 'may be used uninitialized').

Removing uninitialized_var()

Posted Jan 13, 2013 0:39 UTC (Sun) by oak (guest, #2786) [Link]

GCC not detecting all the cases where variable might be uninitialized (and it requiring optimizations enabled to find what it can find) is one thing, but it's not what annoys people. Wrong warnings are what annoy them.

As noted, GCC does these checks using information gathered with the optimization passes. A bug in GCC 4.5 and earlier was that it did the warning before all optimization passes had been done and therefore could give warnings for code paths that weren't relevant (= dead, would never happen). This was (at least mostly) fixed in GCC 4.6 and there is/are bugs about it in the GCC bugzilla.

Even if kernel people wouldn't fix GCC bugs instead of kludging kernel code, at least they could file bugs against GCC, or if there's already a bug on the issue, add a pointer to it and comment in code about which GCC version fixes that bug.

(On quick glance of these kind of bugs in GCC bug tracker, most of them seem to be pretty old and might be already fixed with GCC 4.6, I think they need a bit of a re-testing & cleanup.)


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