我写了一个简单的C ++程序,用它来定义一个类如下:
#include <iostream>
using namespace std;
class Computer
{
public:
Computer();
~Computer();
};
Computer::Computer()
{
}
Computer::~Computer()
{
}
int main()
{
Computer compute;
return 0;
}
当我使用g++
(测试在x86 32位Linux上使用g ++ 4.6.3。)来生成ctors
和dtors
时,我会在第.ctors
部分得到这些定义{1}}。
.globl _ZN8ComputerC1Ev
.set _ZN8ComputerC1Ev,_ZN8ComputerC2Ev
.globl _ZN8ComputerD1Ev
.set _ZN8ComputerD1Ev,_ZN8ComputerD2Ev
在深入研究生成的汇编代码之后,我发现_ZN8ComputerC1Ev
应该是构造类Computer
时使用的函数名,而_ZN8ComputerC2Ev
是类Computer
的名称{1}}的构造函数。同样的事情发生在Computer
的析构函数声明和调用中。
似乎构建了表,链接了构造函数及其实现。
所以我的问题是:
这个构造函数/析构函数的实际内容是什么?
我在哪里可以ELF
格式找到它们?
我转储了相关的.ctors
和.init_array
部分,但我找不到定义_ZN8ComputerC1Ev
和_ZN8ComputerC2Ev
之间关系的元数据...
答案 0 :(得分:2)
这里没有表格。 .globl
和.set
是所谓的汇编程序指令或伪操作。它们向汇编器发出信号,但不一定会产生实际的代码或数据。来自the docs:
.global
符号,.globl
符号
.global
使符号对ld
可见。如果你在你的中定义了符号 部分程序,其值可用于其他部分程序 与之相关的。否则, symbol 从a获取其属性 来自另一个文件的同名符号链接到同一个文件中 程序
.set
符号,表达式将 symbol 的值设置为 expression 。这会更改符号的值和 键入以符合表达式。
因此,您引用的片段确保构造函数可用于链接,以防其他编译单元引用它。您通常在最终ELF中看到的唯一影响是符号表中存在这些符号(如果它尚未被剥离)。
现在,您可能很想知道为什么构造函数有两个不同的名称(例如_ZN8ComputerC1Ev
和_ZN8ComputerC2Ev
)。答案有点复杂,所以我会引用你的另一个问题来详细解决它: