2013-10-21 12 views
3

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」,但究竟什麼是析構函數組又是什麼好?鏗鏘聲++ - 3.3不會發出它,http://gcc.gnu.org/ml/gcc-patches/2011-11/msg00383.html表明它可能與gcc中的新事務內存功能有關。

回答

2

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。這可確保組中的功能全部用於最終的二進制文件中,或者全部丟棄(以執行「一個定義規則」)。

在上述錯誤的討論的結果似乎是:

對於任何類的實現具有使用每 構造/析構一個COMDAT或使用C5/D5 COMDAT的選項。我可以根據任何盈利標準做出該決定。如果使用C5/D5 comdat 的規則是

  • C5 comdat必須有C1和C2。
  • 如果某個類具有虛擬析構函數,則D5 comdat必須具有D0,D1和D2
  • 如果某個類具有非虛擬析構函數,那麼D5 comdat必須只具有D1和D2析構函數。這是事實,即使 實現使用D0,而不是到D1 + _ZdlPv調用來實現 「刪除* 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這可能是爲什麼它不符合上述定義)

相關問題