Reverse Engineering Stack Exchange is a question and answer site for researchers and developers who explore the principles of a system through analysis of its structure, function, and operation. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The beginning of the virtual function table (VFT, also virtual method table, VMT) disasembled by IDA goes as:

 _ZTV13QSystemLocale DCD 0, _ZTI13QSystemLocale, _ZN13QSystemLocaleD2Ev+1, _ZN13QSystemLocaleD0Ev+1

and c++filt decodes it as

 vtable for QSystemLocale DCD 0, typeinfo for QSystemLocale, QSystemLocale::~QSystemLocale()+1, QSystemLocale::~QSystemLocale()+1

Here we see _ZN13QSystemLocaleD2Ev and _ZN13QSystemLocaleD0Ev, both transformed by c++filt to QSystemLocale::~QSystemLocale().

(+1 is normal, the bit selects the right instruction set on ARM).

The Qt source declares:

virtual ~QSystemLocale();

Why there are two virtual destructors?

(I work with ARM, Android NDK (gcc/g++), C++, Qt).

share|improve this question
up vote 5 down vote accepted

According to documentation the first one is base object destructor and the second one is deleting destructor.

Constructors and destructors are simply special cases of <unqualified-name>, where the final <unqualified-name> of a nested name is replaced by one of the following:

  <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

According to ARM IHI 0041D document the difference between these destructors is as follows:

This ABI requires C1 and C2 constructors to return this (instead of being void functions) so that a C3 constructor
can tail call the C1 constructor and the C1 constructor can tail call C2.
Similarly, we require D2 and D1 to return this so that D0 need not save and restore this and D1 can tail call D2 (if
there are no virtual bases). D0 is still a void function.
share|improve this answer
Is Itanium ABI relevant to ARM? – 18446744073709551615 May 13 '14 at 9:00
I've seen the same things in ARM abi documents. The difference between these destructors is restoring and preserving "this" pointer. I'll update the answer. – w s May 13 '14 at 9:06
@18446744073709551615: yes. It's relevant to many C++ implementations, regardless of platform. – Igor Skochinsky May 13 '14 at 11:11
@ws: in fact, the difference is that the deleting destructor must deallocate the memory occupied by the object, in addition to destructing the members. I.e. it's used to implement the delete pObj; statements. The return value convention is mandated by ARM to reduce code duplication but it's not a requirement of the the base C++ ABI. – Igor Skochinsky May 13 '14 at 11:15
Also – Vitaly Osipov May 14 '14 at 2:29

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.