【问题标题】:What is a "destructor group" symbol in gcc name mangling什么是 gcc 名称修改中的“析构函数组”符号
【发布时间】:2013-10-29 09:12:49
【问题描述】:

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 中的新事务内存功能有关。

【问题讨论】:

    标签: c++ constructor g++ destructor demangler


    【解决方案1】:

    This LLVM patchthis GCC bug 提供更多背景信息。通过以下链接,我找到了Bug 3187 - gcc lays down two copies of constructors,这似乎是这一切的起源:

    构造函数和析构函数的两个(有时是三个)相同的副本 被放下。链接器不会失败,但生成的二进制文件 比实际需要大 20%(在我们的实际示例中)。

    如果您搜索“PR c++/3187” (e.g.),您可以找到许多关于 gcc-patches ML 的讨论。基本上,C5/D5 本身不是构造函数/析构函数,而是包含两个或多个“基本”构造函数/析构函数的COMDAT group。这确保了组中的函数要么全部用于最终的二进制文件,要么全部丢弃(以强制执行“一个定义规则”)。

    上述bug中讨论的结果似乎是:

    对于任何类,实现都可以选择每个类使用一个 comdat 构造函数/析构函数或使用 C5/D5 comdat。我可以这样做 基于任何盈利标准的决策。如果使用 C5/D5 comdat 规则是

    • C5 comdat 必须具有 C1 和 C2。
    • 如果类具有虚拟析构函数,则 D5 comdat 必须具有 D0、D1 和 D2
    • 如果类具有非虚拟析构函数,则 D5 comdat 必须仅具有 D1 和 D2 析构函数。这是真的,即使 实现使用 D0 而不是调用 D1 + _ZdlPv 来实现 “删除*x”

    您可以通过例如查看命令使用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 这可能是它与上面的定义不匹配的原因)

    【讨论】:

      猜你喜欢
      • 2011-02-11
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      • 2020-10-12
      • 2011-08-08
      • 2016-08-05
      相关资源
      最近更新 更多