C++ 链接和名称损坏是如何工作的?

C++ 链接和名称损坏是如何工作的?,c++,linker,declaration,C++,Linker,Declaration,让我们以这段代码为例 //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++文件都知道它需要什么,返回什么。虽然两个重载中的每一个都需要有一个

让我们以这段代码为例

//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上广泛使用的。Windows有不同的格式,但其原理可以预期是相同的。
在iTunum(和ARM)平台上可以找到名字的缩写。< /P> @汤姆:我不记得,但我肯定C++标准并没有强制使非外部变量对其他文件可见。但这也不是一成不变的,你的问题不是很清楚。“当编译器看到第一个myfunc方法[,]时,它不关心A或B,因为它是内部使用的。”实际上,它关心B是为了命名myfunc。你能澄清一下你想说(问)什么吗?@Adrian:可能会在意,但它不需要将参数名作为损坏名称的一部分。我试图询问需要与其他对象文件共享的数据,链接器如何匹配这些对象(头文件可能不同,并且很可能有不同的定义,例如调试和发布。@acidzombie:对,它不关心参数名称,但关心参数类型。我看到您选择了一个答案,但我仍然不理解这个问题。@Adrian:原来elf手册没有这些信息。更好的问题是,两个.cpp文件和链接器如何知道与.cpp文件匹配的重载不具有相同的信息(例如:两个15个字母的类具有字母差异,但结构大小相同,为什么名称不冲突)嗯,我没有-1。我要说的是维基百科没有提到变量命名或其他使其他编译文件可见的东西。这不是答案。我跳了枪。我看到了符号表和外部libs/动态加载,但我没有看到任何关于如何查找/匹配名称的内容