Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading operator delete in a base class

From the C++ standard (ISO/IEC 14882:2003(E)), §12.5.4, about overloading operator delete:

If a delete-expression begins with a unary :: operator, the deallocation function's name is looked up in global scope. Otherwise, if the delete-expression is used to deallocate a class object whose static type has a virtual destructor, the deallocation function is the one found by the lookup in the definition of the dynamic type's virtual destructor (12.4). Otherwise, if the delete-expression is used to deallocate an object of class T or array thereof, the static and dynamic types of the object shall be identical and the deallocation function's name is looked up in the scope of T. If this lookup fails to find the name, the name is looked up in the global scope. If the result of the lookup is ambiguous or inaccessible, or if the lookup selects a placement deallocation function, the program is ill-formed.

§12.5.7 is also interesting:

Since member allocation and deallocation functions are static they cannot be virtual. [Note: however, when the cast-expression of a delete-expression refers to an object of class type, because the deallocation function actually called is looked up in the scope of the class that is the dynamic type of the object, if the destructor is virtual, the effect is the same. For example,

struct B {
    virtual ˜B();
    void operator delete(void*, size_t);
};
struct D : B {
    void operator delete(void*);
};
void f()
{
    B* bp = new D;
    delete bp; // uses D::operator delete(void*)
}

Here, storage for the non-array object of class D is deallocated by D::operator delete(), due to the virtual destructor.]

After reading this, I am wondering...

  • Is this part of the standard fully supported by all major C++ compilers (MSVC++, GCC)?
  • If so, how did they do it? Hidden virtual function? "Special" virtual destructor call? RTTI?
  • Using the example from the standard: can there be problems if f() and D::operator delete() are defined in separate EXE/DLL/DSOs? (Assuming that everything is compiled using the same compiler, of course)

§5.3.5.5 may also be relevant:

In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

like image 849
Etienne Dechamps Avatar asked Jun 15 '11 09:06

Etienne Dechamps


1 Answers

I don't know much about VC++ ABI, but the Itanium ABI is well documented.

Looking up at the name mangling scheme, one see:

<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

Of interest: D0 # deleting destructor, which means that even though delete is non virtual, since it is called from the virtual destructor, it can be considered virtual for all effects and purposes.

like image 194
Matthieu M. Avatar answered Sep 21 '22 22:09

Matthieu M.