samedi 1 avril 2017

aligned_alloc memory block in a copy assignment constructor crashes while being freed

I am maintaining some legacy code which was missing a copy assignment constructor in a managed Aligned Pointer class. I added one as follows (simplified view):

#include <iostream>
#include <cstring>
#include <stdlib.h>

template <class T, unsigned AlignB> 
class AlignedPtr {
private:
    T *mpBlock;
    unsigned mBlkSize;
public:
    // Size specific Ctor
    AlignedPtr(unsigned uNum) : 
    mpBlock(static_cast<T*>  (aligned_alloc(uNum*sizeof(T),  AlignB))),
    mBlkSize(uNum) {}
    // Default, empty Ctor
    AlignedPtr(void) : mpBlock(nullptr), mBlkSize(0) {}
    // Copy Assignment Ctor
    AlignedPtr& operator=(const AlignedPtr& x)
    {
        T *mpNewBlock(static_cast<T*>(aligned_alloc(x.mBlkSize*sizeof(T), AlignB)));
        for (size_t index=0; index < x.mBlkSize; index++) {
            mpNewBlock[index] = x.mpBlock[index];
        }
        free(mpBlock);
        mpBlock  = mpNewBlock;
        mBlkSize = x.mBlkSize;
        return *this;
    }
    // Destroy managed pointer
    ~AlignedPtr() {
        free(mpBlock);
    }
};

int main(int argc, char *argv[])
{

    AlignedPtr<float, 16> first_ptr;
    std::cout << "Pointer Initialized" << std::endl;

    first_ptr = AlignedPtr<float, 16>(8);
    std::cout << "Pointer Re-initialized" << std::endl;

    return 0;
}

My expectation was that the program will terminate normally, however I saw AlignedPtr Dtor fail when first_ptr goes out of scope (main termination). I compile above without any optimizations as:

g++ -std=c++11 -g aligned_alloc_bug.cpp -o aab

On a Ubuntu 14.04 with g++ 4.8.2 and get the following run-time error:

Pointer Initialized
Pointer Re-initialized
*** Error in `./aab': free(): invalid next size (fast): 0x0000000001cf9080 ***
Aborted (core dumped)

Interestingly when I replace aligned_alloc with malloc or posix_memalign for that matter program terminates correctly. Is this a bug in aligned_alloc or am I missing something basic?

P.S: 1) I did a brief search for a gcc bug which returned false. 2) Advise to avoid managing raw pointers is acknowledged in advance but I would appreciate any help for the problem at hand.

Aucun commentaire:

Enregistrer un commentaire