Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 846
Paul J. Lucas Avatar asked Mar 25 '11 20:03

Paul J. Lucas


1 Answers

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)

like image 199
aschepler Avatar answered Sep 30 '22 01:09

aschepler