C++多析构函数?

| 分类 C-Family  | 标签 c++ 

一个宕机的堆栈里面发现个有意思的事情:类 A 的析构函数在调用它自己:

...
A::~A()
A::~A()
...

觉得很奇怪,后来自己试了一个简单的例子,发现只要 析构函数为 virtual 就会生成多个析构函数。duckduckgo 了一下,找到了原因,参考: http://stackoverflow.com/questions/6921295/dual-emission-of-constructor-symbols?lq=1http://stackoverflow.com/questions/6613870/gnu-gcc-g-why-does-it-generate-multiple-dtors

摘录一下:

1 G++ 生成的 ABI 遵循 http://mentorembedded.github.io/cxx-abi/abi.html

We'll start by declaring that GCC follows the Itanium C++ ABI.


According to the ABI, the mangled name for your Thing::foo() is easily parsed:

_Z     | N      | 5Thing  | 3foo | E          | v
prefix | nested | `Thing` | `foo`| end nested | parameters: `void`

You can read the constructor names similarly, as below. Notice how the constructor "name" isn't given, but instead a C clause:

_Z     | N      | 5Thing  | C1          | E          | i
prefix | nested | `Thing` | Constructor | end nested | parameters: `int`

But what's this C1? Your duplicate has C2. What does this mean?

Well, this is quite simple too:

  <ctor-dtor-name> ::= C1   # complete object constructor
                   ::= C2   # base object constructor
                   ::= C3   # complete object allocating constructor
                   ::= D0   # deleting destructor
                   ::= D1   # complete object destructor
                   ::= D2   # base object destructor

2 G++ 生成多个析构函数,其意义如下

(参考: http://stackoverflow.com/questions/6613870/gnu-gcc-g-why-does-it-generate-multiple-dtors/6614369#6614369)

  • D2 is the "base object destructor". It destroys the object itself, as well as data members and non-virtual base classes.
  • D1 is the "complete object destructor". It additionally destroys virtual base classes.
  • D0 is the "deleting object destructor". It does everything the complete object destructor does, plus it calls operator delete to actually free the memory.

3 D0~D3 的调用顺序

  1. 示例 1:
    1: class A
    2: {
    3: public:
    4:     A(){}
    5:     virtual ~A(){}
    6: };
    7: 
    8: A* a = new A;
    9: delete a;
    

    顺序: DA0 -> DA1 -> DA0

  1. 示例 2:
     1: class A
     2: {
     3: public:
     4:     A(){}
     5:     virtual ~A(){}
     6: };
     7: 
     8: class B: public A
     9: {
    10: public:
    11:     B(){}
    12:     virtual ~B(){}
    13: };
    14: 
    15: A* a = new B;
    16: delete a;
    

    顺序: DB0 -> DB1 -> DA1 -> DB1 -> Db0


上一篇     下一篇