Checking rules for structured variables in GCC
Consider the following program C
#include <stdio.h>
typedef struct s {
int x;
} s_t;
int main() {
int x;
s_t a;
scanf("%d", &x);
if (x > 0) {
s_t a;
a.x = x;
}
printf("%d\n", a.x);
}
The structured variable a
in the if branch clearly highlights the structured variable a
in the main. One would expect the output in printf to be undefined, but with GCC the visible variable seems to be equal to the main variable.
for example
gcc test.c -o test
echo 10 | ./test
will output 10.
On the other hand, doing this through clang as expected
clang test.c -o test
echo 10 | ./test
outputs -2145248048.
Is this a GCC bug or is there some undefined behavior that gets triggered?
gcc 4.8.2 clang 3.4
source to share
As mentioned, you are reading an uninitialized local variable and undefined. So everything is legal. Having said that, there is a special reason for this behavior: gcc
reuses variables on the stack (for example, until the generated code is plausible). You can make fine adjustments using the parameter -fstack-reuse
.
To disable stack reuse:
gcc test.c -o test -fstack-reuse=none
echo 10 | ./test
4195808 # prints some random number.
To enable stack reuse for all variables:
gcc test.c -o test -fstack-reuse=all #, or -fstack-reuse=named_vars
echo 10 | ./test
10 # prints 10, as it reuses the space on the stack.
This is fully described in GCC Code Generation Options .
source to share
Is this a GCC bug or is there some undefined behavior that gets triggered?
This behavior is undefined. s_t a;
in the statement if
hides the previous declaration a
.
In the block
if (x > 0) {
s_t a;
a.x = x;
}
x
assigned to local a.x
. After this block is a
no longer available, and in printf
you you get access to an uninitialized variable. Uninitialized variables can call UB.
source to share