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

问题描述:

我正在维护一些遗留代码,这些遗留代码在托管对齐指针类中缺少复制分配构造函数。我加了一个如下(简化视图):aligned_alloc复制分配构造函数中的内存块在释放时崩溃

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

我的期望是,该方案将正常结束,但是我看到的时候 first_ptr超出范围(主终端)AlignedPtr析构函数失败。 我编译以上无需任何优化为:

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

在一个Ubuntu的14.04使用g ++ 4.8.2,并获得以下的运行时错误:

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

有趣的是,当我更换 aligned_alloc malloc posix_memalign因此,程序正常终止。这是一个错误 aligned_alloc或我缺少一些基本的东西?

P.S:1)我做了一个简短的搜索gcc错误返回false。 2)建议避免管理原始指针提前得到确认,但我希望能够帮助解决手头的问题。

+1

你遵循三规则? –

+0

@Kerrek SB我做过,完整的程序也有自定义拷贝构造函数。 – fsheikh

+0

我认为这是因为在赋值运算符中,您正在读取4字节边界,但内存分配的是16字节,预计读取将在16字节边界。 请尝试使用valgrind获取更多信息。 – AquaAsh

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

void *aligned_alloc(size_t alignment, size_t size);

这就导致内存崩溃,这时候你打电话free只检测。

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

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

我意识到,但谢谢你的答案,感激地接受。 – fsheikh

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

+1

因为我在拷贝分配中分配新内存我不认为我的对象指向相同的内存。话虽如此,我已经做了一个更基本的错误,即使用aligned_alloc函数的不正确参数顺序。我错误地认为aligned_alloc与WIN32 aligned_malloc具有相同的签名。多么想念...... – fsheikh