Linker Resolution of Multi-Defined Global Symbols

Before we start, we have to clarify two concepts, strong symbols and weak symbols.
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!

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326633709&siteId=291194637