C++ 和 Java 中链接器符号的重整
C++ 和 Java 中链接器符号的重整
C++ 和 Java 都允许重载方法,这些方法在源代码中有相同的名字,却有不同的参数列表。那么链接器是如何区别这些不同的重载函数之间的差异呢?
C++ 和 Java 中能使用重载函数,是因为编译器将每个唯一的方法和参数列表组合编码成一个对链接器来说唯一的名字。这种编码过程叫做重整(mangling),而相反的过程叫做恢复 (demangling) 。
幸运的是,C++ 和 Java 使用兼容的重整策略。
一个被重整的类名字是由名字中字符的整数数量,后面跟原始名字组成的。比如,类
Foo被编码成3Foo。方法被编码为原始方法名,后面加上
__,加上被重整的类名,再加上每个参数的单字母编码。比如,Foo::bar(int, long)被编码为bar__3Fooil。重整全局变量和模板名字的策略是相似的。
Linux 中,解析多重定义的全局符号
强/弱符号
函数和已初始化的全局变量是强符号
未初始化的全局变量是弱符号
根据强弱符号的定义,Linux 链接器使用下面的规则来处理多重定义的符号名:
规则 1:不允许有多个同名的强符号。
规则 2:如果有一个强符号和多个弱符号同名,那么选择强符号。
规则 3:如果有多个弱符号同名,那么从这些弱符号中任意选择一个。
下面是一个例子:
/* foo.c */
#include <stdio.h>
void f(void);
int y = 15212;
int x = 15213;
int main()
{
f();
printf("x=0x%x y=0x%x\n", x, y);
return 0;
}
/* bar.c */
double x;
void f()
{
x=-0.0;
}
在上面的例子中,输出结果如下,因为 double 为 8 个字节,而 int 为 4 个字节,因此赋值 x=-0.0 会覆盖内存中 x 和 y 的位置。
linux> ./foobar
x=0x0 y=0x80000000
参考资料:
《深入理解计算机系统》P471
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 LinJHS
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

