At compile time, the compiler exports each global symbol to the assembler as either strong or weak , and the
assembler encodes this information implicitly in the symbol table of the relocatable object file.
编译的时候,symbol会被划分成 strong 和 weak两种。
Functions and initialized global variables get strong symbols.
Uninitialized global variables get weak symbols.
For the example program in Figure 7.1, buf, bufp0, main, and swap are strong symbols; bufp1 is a weak
symbol.
symbol resolution的规则。
Given this notion of strong and weak symbols, Unix linkers use the following rules for dealing withmultiplydefined
symbols:
Rule 1: Multiple strong symbols 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.
一个比较小的,但严重的错误
The application of Rules 2 and 3 can introduce some insidious run-time bugs that are incomprehensible to
the unwary programmer, especially if the duplicate symbol definitions have different types. Consider the
following example, where x is defined as an int in one module and a double in another:
1 /* foo5.c */
2 #include <stdio.h>
3 void f(void);
4
5 int x = 15213;
6 int y = 15212;
7
8 int main()
9 {
10 f();
11 printf("x = 0x%x y = 0x%x /n",
12 x, y);
13 return 0;
14 }
1 /* bar5.c */
2 double x;
3
4 void f()
5 {
6 x = -0.0;
7 }
On an IA32/Linux machine, doubles are 8 bytes and ints are 4 bytes. Thus, the assignment x = -0.0
in line 5 of bar5.c will overwrite the memory locations for x and y (lines 5 and 6 in foo5.c) with the
double-precision floating-point representation of negative one!
linux> gcc -o foobar5 foo5.c bar5.c
linux> ./foobar5
x = 0x0 y = 0x80000000
用gcc的选项来 提示多出定义。
When in doubt, invoke
the linker with a flag such as the GCC -warn-common flag, which instructs it to print a warning message
when it resolves multiply-defined global symbol definitions.