When I teach C, sometimes I count on GCC to do the "convincing" part of some rules. For example, one should not consider that a local variable on a function retains the value between calls.
GCC always helped me to teach these lessons to students, putting garbage on local variables, so they understand what is happening.
Now, this piece of code is definitely causing me a hard time.
#include <stdio.h>
int test(int x)
{
int y;
if(!x)
y=0;
y++;
printf("(y=%d, ", y);
return y;
}
int main(void)
{
int a, i;
for(i=0; i<5; i++)
{
a=test(i);
printf("a=%d), ", a);
}
printf("\n");
return 0;
}
The output is:
(y=1, a=1), (y=2, a=2), (y=3, a=3), (y=4, a=4), (y=5, a=5),
But if I comment the line:
/* printf("(y=%d, ", y); */
Then the output become:
a=1), a=32720), a=32721), a=32722), a=32723),
I compile the code using -Wall
switch, but no warnings are related to the use of local variables without initializing them.
Is there any GCC switch to cause a warning, or at least to explicit show some garbage? I tried the optimization switches, and that helped as the code output became like this:
$ gcc test.c -o test -Wall -Os
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -Ofast
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O0
$ ./test
(y=1, a=1), (y=2, a=2), (y=3, a=3), (y=4, a=4), (y=5, a=5),
$ gcc test.c -o test -Wall -O1
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O2
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O3
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
But y=1 in all cases is kind of trick. Does the standard changed so the local variables are now initialized with zeros?
That's the problem with undefined behaviour: it's "undefined".
So, any set of results is entirely down to a combination of compiler/settings/what's in memory/interrupts.
You may chance upon some settings that output what you "expect", to demonstrate the problem - but that's just luck.
What you've discovered is actually more important - that the number of failure modes is wider than you can imagine (although luckily, none has reformatted your hard drive yet), and that the most pernicious and dangerous type of 'undefined behaviour' is that where the behaviour is actually 'as expected' for 99.99% of the time.
It's the 0.01% that gets you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With