The so-called strong symbols refer to functions and initialized global variables. Natural weak symbols refer to uninitialized global variables.
In Unix systems, the linker adopts the following rules to deal with multiple defined global symbols:
1. Multiple identical strong symbols are not allowed in the same file.
2. If an object has one strong symbol and multiple weak symbols, choose the strong symbol.
3. If there are multiple weak symbols, choose one.
Now, in human language, let’s explain the rules a little bit with examples.
1. The case of multiple strong symbols:
//main.c #include<stdio.h> void foo(); int x = 1513; // strong sign int main(void){ return 0; }
#include<stdio.h> int x = 2222; // strong sign void foo(){ ; }
If you try to link these two files at this point, the compiler will report an error because the strong symbol x is defined multiple times.
2. The case of a strong symbol:
//main.c #include<stdio.h> void foo(); int x = 1513; // strong sign int main(void){ foo(); printf("x=%d\n", x); return 0; }
//foo.c #include<stdio.h> int x; // weak sign void foo(){ x = 2222; }
At this point, the output of linking these two files is: x=2222.
3. Without strong symbols:
//main.c #include<stdio.h> void foo(); int x; // weak sign int main(void){ x = 1111; foo(); printf("x=%d\n", x); return 0; }
//foo.c #include<stdio.h> int x; // weak sign void foo(){ x = 2222; }
The output at this time is the same as the above example.
For rule 2 and rule 3, it is possible to make mistakes if you are not careful, especially when the repeated symbol definitions have different types, as in the following example:
//main.c #include<stdio.h> void foo(); int x = 1513; // strong sign, int type int z = 3333; // strong sign int main(void){ foo(); printf("x=%d, z=%d\n", x, z); return 0; }
//foo.c double x; //weak sign, double type void foo(){ x = 0.0; }
The output at this point will be "surprising": x=0, z=0 ! !
Why is this so? Because the global symbol x has different types in the two files, and the strong symbol prevails, the memory referenced by x in the second file is in the first file, but because it converts the int type of x Expanded to double type, and usually in the system double is 8 bytes, int is 4 bytes, so it will cover the next 4 bytes, thus changing the value of z incidentally!