链接和名称篡改是如何工作的
How does linkage and name mangling work?
让我们取这个代码示例
//header
struct A { };
struct B { };
struct C { };
extern C c;
//code
A myfunc(B&b){ A a; return a; }
void myfunc(B&b, C&c){}
C c;
让我们从代码部分开始逐行执行此操作。当编译器看到第一个myfunc方法时,它不关心A或B,因为它的使用是内部的。每个c++文件都会知道它接收了什么,返回了什么。虽然两个重载中的每一个都需要有一个名称,但如何选择,链接器如何知道哪个是什么意思?其次是C C;我曾经有一个错误,链接器无法重新配置,因此允许我访问其他C++文件中的C。这是因为cpp不知道c是extern,我必须在标题中将它标记为extern,然后才能成功链接。现在我不确定类类型是否与链接器和变量C有关。我不知道RTTI将如何涉及,但我知道C需要被其他文件可见。
链接器是如何工作的以及名称篡改等等。
我们首先需要了解编译结束和链接开始的位置。编译包括获取一个编译单元(一个C或C++源文件)并将其转换为一个对象文件。简单地说,这包括为每个函数生成机器代码片段,以及为所有函数和静态(全局)变量生成符号表。占位符用于编译单元所需的在所述编译单元外部的任何符号。
然后,链接器负责加载所有对象文件,并解析具有实际地址(或机器独立代码的偏移量)的所有占位符符号。它被放置在操作系统的动态加载程序在加载可执行文件时可以读取的各个部分中。
具体情况也是如此。为了避免链接过程中出现错误,编译器要求您声明当前编译单元将使用的所有外部符号。对于全局变量,必须使用extern
关键字,对于函数,这是可选的。
编译单元中定义的所有函数和全局变量都有外部链接(即,可以被其他编译单元引用),除非用static
关键字(或C++中未命名的命名空间)声明。在C++中,vtable还将具有链接所需的符号。
现在在C++中,由于函数可以重载,因此参数也构成了函数名称的一部分。由于机器代码只是地址和寄存器,因此需要在符号表中的函数名称中添加额外的信息。这些额外的参数信息以损坏的名称的形式出现,并确保链接器链接到重载函数的正确版本。
如果你真的对血腥的细节感兴趣,可以看看Linux上广泛使用的ELF文件格式(PDF)。Windows有不同的格式,但原理可以预期是相同的。Itanuim(和ARM)平台上的名称篡改可以在这里找到。
http://en.wikipedia.org/wiki/Name_mangling
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?