add2.c:
int counter=0;
int a=0;
int b;
int c;
int add(int a, int b) {
return a+b;
}
Run Code Online (Sandbox Code Playgroud)
编译:gcc -c add2.c -o add2.o
阅读符号表:readelf --symbols add2.o
Symbol table '.symtab' contains 12 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS add2.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 2
4: 00000000 0 SECTION LOCAL DEFAULT 3
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 4
7: 00000000 4 OBJECT GLOBAL DEFAULT 3 counter
8: 00000004 4 OBJECT GLOBAL DEFAULT 3 a
9: 00000004 4 OBJECT GLOBAL DEFAULT COM b
10: 00000004 4 OBJECT GLOBAL DEFAULT COM c
11: 00000000 14 FUNC GLOBAL DEFAULT 1 add
Run Code Online (Sandbox Code Playgroud)
"COM"在Ndx列中的含义是什么?我理解"#"和"a"在#3部分(即.bss)中定义,"add"在#1部分(即.text)中定义,但我期待"b"和"c"也在.bss部分中定义,因此在Ndx列中得到"3".
谢谢
gcc处理未初始化的全局变量,这些全局变量未明确声明extern为"常用"符号(因此为"COM").
在创建最终可执行文件时,链接器将相同公共符号的多个定义(跨多个目标文件)合并在一起,以便它们都引用相同的存储.其中一个目标文件可以将其初始化为特定值(在这种情况下,它将最终出现在数据部分中); 如果没有对象文件初始化它,将最终在BSS中; 如果多个对象初始化它,您将收到链接器错误.
总之,如果你有两个定义int a:
int a;在一个对象和int a;另一个对象中是OK:两者都引用相同a,初始化为0int a;在一个对象和int a = 42;另一个对象中是OK:两者都指向相同的a,初始化为42int a = 23;在一个对象和int a= 42;另一个对象中将给出链接错误.请注意,标准C在技术上不允许在两个对象上使用相同符号的多个定义; 但许多编译器都支持它,包括gcc,作为扩展.(它被列在"共同扩展"下 - 在C99规范中没有双关语.)