Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The local variables are not static but why do I get this behaviour?

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?

like image 768
DrBeco Avatar asked Jun 13 '13 18:06

DrBeco


Video Answer


1 Answers

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.

like image 118
Roddy Avatar answered Sep 19 '22 00:09

Roddy