【发布时间】:2016-09-12 01:26:47
【问题描述】:
我对 C 链接中的符号解析(尤其是 elf 格式)有疑问。
假设我将两个模块拆分为单独的文件 module1.c 和 module2.c:
// module1.c
int main() {
return 0;
}
==========================
// module2.c
int main = 3;
int p2() {
return 0;
}
将这两个编译在一起会给我一个链接器错误,因为两个模块中的 main 有一个重复的符号。我的问题是,为什么链接器不考虑一个是函数而一个是变量的事实?此信息肯定存在于两者的符号表中:
Symbol table '.symtab' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS a.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 4
8: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 main
No version information found in this file.
===================================================================
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS b.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 4
8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 main
9: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 p2
您可以清楚地看到一个是对象,另一个是函数。我的问题是,链接器是否有任何特定原因不打算在函数和变量之间进行这种区分?这是否意味着在一个由许多模块组成的庞大程序中,你永远不能声明一个与函数同名的全局变量?
【问题讨论】:
-
因为函数和变量没有不同的命名空间,请参阅标准。并且链接器不知道对象的类型。
-
@Olaf 但它可能知道函数和变量之间的区别,它不像信息不在目标文件中。我的问题是它是否有特殊的原因没有做出区分。
-
那么您将如何解决
void *p = &main;之类的问题?或者在函数也是对象的语言中?或者... -
@Olaf 这是一个很好的例子。