https://stackoverflow.com/a/6614369/1091587当您阅读使用“gcc3”类型名称改编编译的程序的符号表时,会出现析构函数类型(D0、D1、D2)的简要概述。还有相应的构造函数C0/C1/C2。在 g++-4.7(可能更早)中,出现了一个新的 ctor/dtor 对,即 C5/D5,但仅作为调试符号。
$ cat i.cpp
class X { public: virtual ~X() {}; };
int main(void) { X x; return 0; };
$ g++ -c i.cpp
$ nm i.o | grep 5
0000000000000000 n _ZN1XC5Ev
0000000000000000 n _ZN1XD5Ev
$ c++filt -n _ZN1XC5Ev _ZN1XD5Ev
X::X()
X::~X()
demangler 源将 D5 对象称为“gnu_v3_object_dtor_group”,但 dtor 组到底是什么,它有什么用? clang++-3.3 不发出它,http://gcc.gnu.org/ml/gcc-patches/2011-11/msg00383.html表明它可能与 gcc 中的新事务内存功能有关。
最佳答案
This LLVM patch和 this GCC bug提供更多背景。通过点击我找到的链接 Bug 3187 - gcc lays down two copies of constructors这似乎是这一切的起源:
Two (sometimes three) identical copies of constructors and destructors are laid down. The linker doesn't fail this, but the binaries produced are 20% bigger (on our real-world example) than necessary.
如果您搜索“PR c++/3187”(e.g.),您可以找到许多关于 gcc 补丁 ML 的讨论。基本上,C5/D5 本身不是构造函数/析构函数,而是一个 COMDAT group。包含两个或多个“基本”构造函数/析构函数。这确保组中的函数要么全部用于最终二进制文件,要么全部丢弃(以强制执行“一个定义规则”)。
上面bug的讨论结果好像是:
For any class an implementation has the option of using one comdat per constructor/destructor or using a C5/D5 comdat. I may make that decision based on any profitability criterion. If using a C5/D5 comdat the rules are
- A C5 comdat must have C1 and C2.
- If a class has a virtual destructor, the D5 comdat must have D0, D1 and D2
- If a class has a non-virtual destructor, the D5 comdat must have only the D1 and D2 destructors. That is true even if the implementation uses D0 instead of a call to D1 + _ZdlPv to implement "delete *x"
您可以通过例如查看 comdats使用 readelf -G
转储文件:
COMDAT group section [ 1] `.group' [_ZN1XD5Ev] contains 2 sections:
[Index] Name
[ 10] .text._ZN1XD2Ev
[ 12] .text._ZN1XD0Ev
COMDAT group section [ 2] `.group' [_ZN1XC5Ev] contains 1 sections:
[Index] Name
[ 14] .text._ZN1XC2Ev
(这与 GCC 4.6 相关,这可能是它与上述定义不匹配的原因)
关于c++ - gcc名称修改中的 "destructor group"符号是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19485012/