Global variables with the same name
You know from the Build process that the compiler will export the global variables to the assembler
and the assembler encode these variables implicitly and put them in the symbol table of object file and finally the linker take these object files and produce .elf or .dwarf .
Theses global variables can be weak symbols or strong symbols:
The weak symbol is the unintialized variable and the strong symbols are the intialized variables and functions.
The linker use the following rules to deal with the multiple defined global variables
Rule 1: Multiple strong symbols (with same variable name) are not allowed.
Rule 2: Given a strong symbol and multiple weak symbols, choose the strong symbol.
Rule 3: Given multiple weak symbols, choose any of the weak symbols.
/* test1.c */
int x = 1521;
int main()
{
return 0;
}
/* test2.c */
int x = 1521;
void f()
{
}
Based on the rule1 the linker will produce error because the strong symbol x is defined twice .
/* test1.c */
void f(void);
int x = 15213;
int main()
{
f();
printf("x = %d\n", x);
return 0;
}
/* test2.c */
int x;
void f()
{
x = 15212;
}
At run time, function f() changes the value of x from 15213 to 15212 .Notice that the linker normally gives no indication that it has detected multiple definitions of x.(rule2)
The same thing can happen if there are two weak definitions of x (rule 3):
/*test1.c*/
#include <stdio.h>
void b(void);
int x;
int main()
{
x = 2016;
b();
printf("x = %d ",x);
return 0;
}
/*test2.c*/
#include <stdio.h>
int x;
void b()
{
x = 2017;
}
The application of rules 2 and 3 can introduce some insidious run-time bugs that are unclear to the unwary programmer, especially if the duplicate symbol definitions have different types.
Example : “x” is defined as an int in one module and a double in another.
/*a.c*/
#include <stdio.h>
void b(void);
int x = 2016;
int y = 2017;
int main()
{
b();
printf("x = 0x%x y = 0x%x \n", x, y);
return 0;
}
/*b.c*/
double x;
void b()
{
x = -0.0;
}
This program will produce x = 0x0 y = 0x80000000
as x is double and y & x in the another file are integer and x took the double size of both of two variables
so y is got corrupted
So to avoid these tricky bugs you can use
gcc -fno-common flag, which triggers an error if it encounters multiply defined global symbols.