Getting issue with placement new and delete operator

Viewed 186

I have written the following code for placement new and delete operator functions. Can you please tell the issue with the code below.

// new_operator.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
using namespace std;
class Mem
{
public:
    void* alloc(size_t sz) { return malloc(sz); }
    void dealloc(void* ptr) { free(ptr); }
};

class Object
{
public:
    Object() { cout << "In Constructor Object()" << this << endl; }
    ~Object() { cout << "In Destuctor ~Object()" << endl; }
    void* operator new(size_t sz, Mem* handle)
    {
        Object* x1 = (Object*)handle->alloc(sz);
        return x1;
    }
    void operator delete(void* ptr, Mem* handle)
    {
        cout << "Here\n";
        ((Object*)(ptr))->~Object();
        handle->dealloc(ptr);
    }
};
int main()
{
    Mem* memory = new Mem;
    Object* obj = new (memory) Object;
    cout << "Obj is " << obj << endl;
    delete (obj, memory);
    delete memory;
    return 0;
}

I'm getting runtime crashes at the time when delete operator function starts executing. Can anyone please tell what I'm doing wrong.

2 Answers
  1. Placement delete is called to free memory when a constructor called from placement new fails. You are not supposed to call any destructors from any version of operator delete, because operator delete frees memory that is left after an object that used to reside there is destroyed (or was never constructed to begin with).
  2. The only way to explicitly call a placement operator delete is to spell out two words operator delete, thus making a function-call-expression. You cannot invoke it from a delete-expression (there is no placement-delete-expression syntax). In your case, you would need to use a qualified name: Object::operator delete. Note that if you remove the explicit destructor call from Object::operator delete, as you should because of the above, the destructor will not be called. There is no way to both invoke the destructor and free the memory in a single call to a placement delete. The easiest way to handle this is to create and use a non-static member function, say void Object::destroy(Mem*).
delete (obj, memory);

On this line, you delete only memory, not obj. The left hand operand of comma operator is discarded. Since the expression obj has no side-effects, this is probably a mistake.

delete memory;

On this line, you delete memory again. This results in undefined behaviour.

Note that you never destroy the dynamic Object that you created. The custom placement delete overload will only be called in case the placement new throws an exception. In other cases, your malloc will leak.

Related