add2.c:
int counter=0;
int a=0;
int b;
int c;
int add(int a, int b) {
return a+b;
}
汇编: 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
“COM”在Ndx列中的含义是什么?我理解“#”和“a”在#3部分(即.bss)中定义,“add”在#1部分(即.text)中定义,但我期待“b”和“c”也在.bss部分中定义,因此在Ndx列中得到“3”。
谢谢
答案 0 :(得分:5)
gcc将未初始化的未初始化的全局变量视为“常用”符号(因此为“COM”)。
在创建最终可执行文件时,链接器将相同公共符号的多个定义(跨多个目标文件)合并在一起,以便它们都引用相同的存储。其中一个目标文件可能会将其初始化为特定值(在这种情况下,它将最终出现在数据部分中);如果没有对象文件初始化它,将最终在BSS中;如果多个对象初始化它,您将收到链接器错误。
总之,如果您有extern
的两个定义:
int a
和另一个对象中的int a;
是正常的:两者都引用相同的int a;
,初始化为0 a
和另一个对象中的int a;
是正常的:两者都引用相同的int a = 42;
,初始化为42 a
和另一个对象中的int a = 23;
会出现链接错误。请注意,标准C在技术上不允许在两个对象上使用相同符号的多个定义;但许多编译器都支持它,包括gcc,作为扩展。 (它在“共同扩展”下列出 - 在C99规范中没有双关语。)
答案 1 :(得分:2)
来自this PDF,表7-11:
SHN_COMMON
符号定义相对于 这部分是常见的符号,例如 作为FORTRAN COMMON或未分配的C. 外部变量。这些符号是 有时被称为暂定。
另请参阅this page。
答案 2 :(得分:0)
它们是由链接器分配的未初始化的全局变量。 有时被称为公共变量。
编辑:嗯,保罗贝克打败了我,链接不少。用他的答案:)