我写了一个简单的 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
部分的末尾获取这些定义。
.globl _ZN8ComputerC1Ev
.set _ZN8ComputerC1Ev,_ZN8ComputerC2Ev
.globl _ZN8ComputerD1Ev
.set _ZN8ComputerD1Ev,_ZN8ComputerD2Ev
在深入研究生成的汇编代码后,我发现 _ZN8ComputerC1Ev
应该是构造类 Computer
时使用的函数名称,而 _ZN8ComputerC2Ev
是类 Computer
的构造函数的名称。同样的事情发生在 Computer
的析构函数声明和调用中。
似乎建立了一个表,将构造函数和它的实现联系起来。
所以我的问题是:
这个构造函数/析构函数信息到底有什么用?
我在哪里可以找到它们的
ELF
格式?
我转储了相关的 .ctors
和 .init_array
部分,但我找不到定义 _ZN8ComputerC1Ev
和_ZN8ComputerC2Ev
...
最佳答案
这里没有 table 。 .globl
和 .set
是所谓的汇编程序指令 或伪操作。它们向汇编程序发出信号,但不一定会产生实际代码或数据。来自 the docs :
.global
symbol,.globl
symbol
.global
makes the symbol visible told
. If you define symbol in your partial program, its value is made available to other partial programs that are linked with it. Otherwise, symbol takes its attributes from a symbol of the same name from another file linked into the same program.
.set
symbol, expressionSet the value of symbol to expression. This changes symbol's value and type to conform to expression.
所以你引用的片段只是确保构造函数可用于链接,以防它被其他编译单元引用。您通常在最终 ELF 中看到的唯一效果是符号表中存在这些符号(如果它没有被剥离)。
现在,您可能很好奇为什么构造函数有两个不同的名称(例如 _ZN8ComputerC1Ev
和 _ZN8ComputerC2Ev
)。答案有点复杂,所以我将向您介绍另一个 SO 问题,该问题详细解决了这个问题:
关于c++ - 为什么在 g++ 生成的汇编代码中这样定义构造函数/析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26021243/