aligned_alloc 复制赋值构造函数中的内存块在释放时崩溃

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

我正在维护一些遗留代码,这些代码在托管对齐指针 class 中缺少复制赋值构造函数。我添加了一个如下(简化视图):

#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;
}

我的期望是程序会正常终止,但是我看到 AlignedPtr Dtor 在 first_ptr 超出范围(主要终止)时失败。 我在没有任何优化的情况下编译为:

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

在带有 g++ 4.8.2 的 Ubuntu 14.04 上,出现以下 运行 时间错误:

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

有趣的是,当我将 aligned_alloc 替换为 mallocposix_memalign 就此而言,程序正确终止。这是 aligned_alloc 中的错误还是我遗漏了一些基本的东西?

P.S: 1) 我简单搜索了一个返回 false 的 gcc 错误。 2) 提前确认避免管理原始指针的建议,但对于手头的问题,我将不胜感激。

问题是你有两个对象指向同一个内存:匿名对象和赋值运算符完成后的first_ptr有相同的地址。当他们各自的析构函数被调用时......你可能会猜到会发生什么。

您以错误的顺序将参数传递给 aligned_alloc"documentation"

void *aligned_alloc(size_t alignment, size_t size);

这会导致内存损坏,只有在调用 free 时才会检测到。

此外,您应该考虑实现复制构造函数。这是一个简单的实现:

AlignedPtr(const AlignedPtr& x) { *this = x; }