Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is manually simulating the effects of the delete operator in C++ formally illegal?

I realise this is ill-advised, and I'm not proposing to do it, but I'm curious as to whether the following is actually formally illegal:

#include <iostream>

struct X
{
    ~X()
    {
        std::cout << "~X()\n";
    }
};

int main()
{
    X *x = new X;
    //delete x;
    x->~X();
    ::operator delete(x);
    return 0;
}

It's my understanding that delete x; is equivalent to invoking the destructor and then calling ::operator delete(x);, but is it legal for me to do that manually according to the standard? I know this is a valid thing to when using placement new, but what about in the non-placement case? My hunch is that it might be illegal because delete (and not operator delete) has to be performed for each new, but I'd be interested to know for sure.

like image 552
Stuart Golodetz Avatar asked Dec 12 '10 15:12

Stuart Golodetz


1 Answers

I'm pretty sure that this is not standard compliant. Nowhere in the standard (that I'm aware of) does it say that the operand of delete p; is passed directly to the deallocation function, and for delete [] it almost certainly isn't passed through unchanged.

It will probably work on all practical implementations, however.

For certain, you shouldn't be calling the global deallocation function explicitly. It's fine in your example, which doesn't have user-defined allocation and deallocation functions, but not in the general case (actually, is there any syntax for calling the class-specific deallocation function if it exists, and the global one otherwise?).

Also, in the general case, the pointer passed to the deallocation function is definitely not the operand of delete. Consider:

struct A
{
  virtual ~A() {}
};

struct B1 : virtual A {};

struct B2 : virtual A {};

struct B3 : virtual A {};

struct D : virtual B1, virtual B2, virtual B3 {};

struct E : virtual B1, virtual D {};

int main( void )
{
  B3* p = new D();
  p->~B3(); // should be ok, calling virtually
  operator delete(p); // definitely NOT OK

  return 0;
}
like image 194
Ben Voigt Avatar answered Sep 28 '22 06:09

Ben Voigt