jeudi 1 juin 2017

Destructor called implicitly every time I allocate with placement new

I have the following issue: I am using on my project custom Pool Allocator, and every time I am going to allocate any object with placement new, the destructor is also called on that object implicitly.

Here is the source code:

Test Object:

class Obj {
public:
    Obj(const std::string& s) {  
        std::cout << "Constructor Called" << std::endl; 
    }
    ~Obj() { 
        std::cout << "Destructor Called" << std::endl; 
    }

};

Main:

int main()
{

    void *pmemory;
    pmemory = malloc(ONEGIG_SIZE);

    PoolAllocator* poolAllocator =  new PoolAllocator(sizeof(Obj), __alignof(Obj), ONEGIG_SIZE, pmemory);
    Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello")); //<-- const and dest is called

    //......

    return 0;
}

And here is the source code of Allocator : AllocateNew function:

template <class T> T* allocateNew(Allocator& allocator, const T& t)
{
        return new (allocator.allocate(sizeof(T), __alignof(T))) T(t);
}

Pool Allocator :

PoolAllocator::PoolAllocator(size_t objectSize, u8 objectAlignment, size_t size, void* mem)
        : Allocator(size, mem), _objectSize(objectSize), _objectAlignment(objectAlignment)
{
    ASSERT(objectSize >= sizeof(void*));

    //Calculate adjustment needed to keep object correctly aligned
    u8 adjustment = pointer_math::alignForwardAdjustment(mem, objectAlignment);

    _free_list = (void**)pointer_math::add(mem, adjustment);

    size_t numObjects = (size-adjustment)/objectSize;

    void** p = _free_list;

    //Initialize free blocks list
    for(size_t i = 0; i < numObjects-1; i++)
    {
        *p = pointer_math::add(p, objectSize );
        p = (void**) *p;
    }

    *p = nullptr;
}

PoolAllocator::~PoolAllocator()
{
    _free_list = nullptr;
}

void* PoolAllocator::allocate(size_t size, u8 alignment)
{
    ASSERT(size == _objectSize && alignment == _objectAlignment);

    if(_free_list == nullptr)
        return nullptr;

    void* p = _free_list;

    _free_list = (void**)(*_free_list);

    _used_memory += size;
    _num_allocations++;

    return p;
}

void PoolAllocator::deallocate(void* p)
{
    *((void**)p) = _free_list;

    _free_list = (void**)p;

    _used_memory -= _objectSize;
    _num_allocations--;
}

It seems that the destructor is called after the return o p in allocate method in Pool Allocator! Anyone can explain why this is happening ?

Aucun commentaire:

Enregistrer un commentaire