What's this extra parameter passed into virtual destructor?
Asked Answered
C

3

16

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()?

Cookery answered 8/11, 2011 at 14:43 Comment(14)
I'd suggest you tag this as c++-cliMartellato
@ThomasMcLeod: That's what I see in Visual Studio Disassembly window.Cookery
@Martellato but it's not c++-cli, I don't thinkDanieu
Right, but is this a Debug project configuration or Release?Adroit
See [this answer that shows the meaning of such hidden destructor parameter][1]. [1]: #7750780Hydrotropism
@ThomasMcLeod: That's Release with /O2 optimization.Cookery
@Rup: You are absolutely right. I seriously misread the question.Martellato
test eax,eax is checking for a null pointer. Not sure why it's in release code.Adroit
@Adroit You're explicitly allowed to call delete null;, and there's a chance the new returned a null so it's probably not allowed to optimise it away.Danieu
@ThomasMcLeod: Visual C++ emits really stupid code on some occasions - that very code is to make "delete null pointer" a no-op.Cookery
@Rup: Exactly, except new never returns null, yet Visual C++ still checks that.Cookery
@Rup,@sharp - makes sense now.Adroit
Never mind whether new can return NULL or not (it can if used with std::nothrow), delete still must check for the case when someone calls i.e. delete NULL;Cantharides
@Nemanja Trifunovic: The compiler has all the code so that it can see when new is used without nothrow and therefore can't return null and therefore delete is done on a non-null pointer. The check can be eliminated, just Visual C++ fails to do so.Cookery
D
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

Doctorate answered 8/11, 2011 at 14:54 Comment(0)
E
6

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.

Epicycloid answered 8/11, 2011 at 14:54 Comment(2)
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.Quach
@deft_code: Thanks for that comment: Explains something I've been wondering about for a while!Masaccio
H
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.

Hydrotropism answered 8/11, 2011 at 14:58 Comment(5)
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).Metallic
@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.Hydrotropism
@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 :)Metallic
@MatthieuM.: Hmm, I thought they tried to be binary compatible (like icc), but it seems they don't.Hydrotropism
well, they are compatible at the C level as far as I know :)Metallic

© 2022 - 2024 — McMap. All rights reserved.