15

I have this code:

class Class {
public:
    virtual ~Class() {}
};

int main()
{
    Class* object = new Class();
    delete object;
}

which I compile with Visual C++ 10 and get this disassembly for delete object statement:

delete object;
test        eax,eax  
je          wmain+23h (401041h)  
mov         edx,dword ptr [eax]  
push        1  
mov         ecx,eax  
call        dword ptr [edx]

and this for the actual destructor:

Class::`scalar deleting destructor':
test        byte ptr [esp+4],1  
push        esi  
mov         esi,ecx  
mov         dword ptr [esi],offset Class::`vftable' (402100h)  
je          Class::`scalar deleting destructor'+18h (401018h)  
push        esi  
call        dword ptr [__imp_operator delete (4020A8h)]  
pop         ecx  
mov         eax,esi  
pop         esi  
ret         4

What is that push 1 doing at the call site and why is the test at the destructor entry point checking for that value and conditionally bypass call to operator delete()?

j0k
  • 22,600
  • 28
  • 79
  • 90
sharptooth
  • 167,383
  • 100
  • 513
  • 979

3 Answers3

15

The argument is used by the destructor to know if it should call delete at the end.

3 cases where you don't want to call it :

  • The destructor is called by a derived class destructor
  • The object is allocated on the stack, thus not created with new.
  • The object is a field of another object, thus not created by new

EDIT: Add a third case

crazyjul
  • 2,519
  • 19
  • 26
6

Basically, the virtual destructor also implements calling operator delete. The parameter is there to decide whether or not call it.

See this answer that shows the meaning of such hidden destructor parameter.

Community
  • 1
  • 1
jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • Is this hidden parameter specific to VC++ ? I thought that gcc had chosen the road of generating multiple destructors instead (3 if I remember correctly). – Matthieu M. Nov 08 '11 at 15:27
  • @MatthieuM.: This should be part of the ABI, so gcc should do the same on Windows (if it wants to be compatible). I haven't tried it, though. – jpalecek Nov 08 '11 at 15:48
  • 1
    @jpacelek: ah right, it's in the ABI. Actually, gcc works without this on Windows too... as long as you don't try to mix gcc and VC++ libraries :) – Matthieu M. Nov 08 '11 at 16:02
  • @MatthieuM.: Hmm, I thought they tried to be binary compatible (like icc), but it seems they don't. – jpalecek Nov 08 '11 at 16:11
  • well, they are compatible at the C level as far as I know :) – Matthieu M. Nov 08 '11 at 16:21
5

I believe the extra parameter tells the compiler which destructor is the derived-most one, so that it only deallocates memory once, at the appropriate level of inheritance. I've seen something similar in gcc if I recall correctly.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 3
    GCC emits 3 destructors, for every class: a regular destructor, deallocating destructor, and a subclass destructor. It looks like VS just emits one and calls it with a bool. – deft_code Nov 08 '11 at 14:57
  • @deft_code: Thanks for that comment: Explains something I've been wondering about for a while! – Ben Jackson Nov 08 '11 at 19:20