Paul J. Lucas
Paul J. Lucas

Reputation: 7133

Calling a member-function from within overloaded operator delete?

This article on Binary-compatible C++ Interfaces contains the code:

class Window {
public:
  // ...
  virtual void destroy() = 0;

  void operator delete(void* p) {
    if (p) {
      Window* w = static_cast<Window*>(p);
      w->destroy(); // VERY BAD IDEA
    }
  }
};

To me, that seems wrong: operator delete() works on raw memory with the intended purpose to free it. The object's destructor has already been called, so calling destroy() works on a "phantom" object (if it works at all). Indeed: that's why operator delete() takes a void* and not a Window* (in this case).

So, the design is flawed, right? (If it is correct, why is it correct?)

Upvotes: 5

Views: 420

Answers (3)

Bo Persson
Bo Persson

Reputation: 92271

That is really nasty code, trying to be helpful.

The article says that in COM code should not delete the object, but call obj->destroy() instead. So to be "helpful" the author makes operator delete do the destroy call. Nasty!

Much better would have been to just declare a private operator delete, so the user cannot delete objects and must instead figure out the correct way.

Upvotes: 0

6502
6502

Reputation: 114491

Yes, that code (if labelled C++) is very wrong.

Operator new and delete as you say handle raw memory, not objects.

That article however deals with specific compilers and specific implementation issues so may be that in that restricted context the code works... moreover MS isn't exactly well renowned for how nicely they care about portable C++ (au contraire, indeed) so may be that kind of bad code is (or was in 2002) actually not only working but even a reasonable solution.

Upvotes: 0

aschepler
aschepler

Reputation: 72356

I agree (assuming Window::destroy is not a static member function):

3.8p1: The lifetime of an object of type T ends when: if T is a class type with a non-trivial destructor, the destructor call starts, or [...]

3.8p5: [...] After the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object [...] was located may be used but only in limited ways. ... If the object will be or was of a non-POD class type, the program has undefined behavior if: the pointer is used to access a non-static data member or call a non-static member function of the object, or [...]

(emphasis mine)

Upvotes: 6

Related Questions