Patrick B.
Patrick B.

Reputation: 12363

Non-initialized global variable(s) of different type but with the same name - strange link behaviour

First of all, please help me to find a better title which will describe the situation more accurately. I created the following simplified version of a problem I stumbled on when debugging real-world (embedded) code.

Consider the following code of file t1.c:

#include <stdio.h>

int A;

void f() { printf("%d\n", A); }

extern void g();

void main(void)
{
    g(); A=1; g();
    A++;
    f();
}

and the code of t2.c:

#include <stdio.h>

double A;

void g()
{
    A += 1.0;
    printf("%f\n", A);
}

Now compiling and running the code like this:

gcc -Wall t1.c t2.c -o t && ./t

gives

1.000000
2.000000
1

Note that both files contain a global variable call A which has a different type. I expected a link error because the symbol A exists multiple times.

I actually get a link warning (object size changes in different .o) when I initialize one of the two variables, an error (multiple definitions) when I initialize both of them.

I tried this with gcc 4.7 and 4.4.

Is this expected behavior? If so, is there something I can do to instruct the toolchain (gcc-based) to warn about it?

Is this a bug?

Upvotes: 5

Views: 106

Answers (2)

ouah
ouah

Reputation: 145849

Yes, compile with -fno-common option to get the linker error:

$ gcc -Wall -fno-common -c t1.c
$ gcc -Wall -fno-common -c t2.c
$ gcc t1.o t2.o -o t
t2.o:t2.c:(.bss+0x0): multiple definition of `_A'
t1.o:t1.c:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
$

If you want to compile this in one line you can also pass the --warn-common to the linker (here with --fatal-warnings to have an error instead of a warning):

$ gcc -Wl,--fatal-warnings,--warn-common -Wall t1.c t2.c -o t
/tmp/cc1xQo79.o: warning: common of `_A' overriding smaller common
/tmp/ccLnhxoe.o: warning: smaller common is here
collect2: error: ld returned 1 exit status
$

By default gcc performs various optimizations of C undefined behaviors as an extension. C allows any implementation to stop translation in presence of such a program, so except if you have excellent reasons to do it, you should avoid it.

Upvotes: 4

Drew McGowen
Drew McGowen

Reputation: 11706

To go off of @ouah's answer, I think the reason it's only a warning is because it's an uninitialized variable, so it goes in the .bss section. By initializing the variables, the compiler moves them to the .data section - the fact that .bss overlap is just a warning may be a gcc quirk, though.

Upvotes: 1

Related Questions