为什么这个显式析构函数会导致shared_ptr中的内存损坏?

时间:2011-12-29 10:04:39

标签: c++ destructor valgrind shared-ptr explicit-constructor

此代码有什么问题,我该如何解决?

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <vector>

struct CTest
{
    CTest()
    { std::cout << "ctor CTest" <<std::endl; }

    ~CTest()
    { std::cout << "dtor CTest" <<std::endl; }
};

struct CSlot
{
    CSlot() : m_test(new CTest()), m_num(123)
    { }

    ~CSlot()
    {
        // m_test.reset(); // this line fixed the code but I don't know why
        m_num = -1;
    }

    boost::shared_ptr<CTest> m_test;
    int m_num;
};

int main()
{
    std::vector<CSlot> testVector(1);

    std::cout << "1" << std::endl;
    new (&testVector[0]) CSlot();

    // clear slot
    testVector[0].~CSlot();
    std::cout << "2" << std::endl;
}

此代码看起来像工作,并打印:

ctor CTest
1
ctor CTest
dtor CTest
2

但有时程序崩溃和valgrind总是说:

==13372== Invalid read of size 4
==13372==    at 0x400D8F: boost::detail::atomic_exchange_and_add(int*, int)
...

我可以使用m_test.reset()行修复此行为,但我认为有更正确的解决方案......

1 个答案:

答案 0 :(得分:6)

因为你所做的事情毫无意义。您正在创建一个对象,然后......在同一地址上创建一个对象。

然后你正在摧毁那个地址上的物体......然后你再次摧毁它。

这应该如何运作?

您要求提供CSlot个对象的向量,这就是您所拥有的。您要求它的大小为1,因此它包含一个CSlot对象,完全构造并准备好执行操作。因此,在它上面构造一个CSlot对象是没有意义的。

如果你想使用placement new并直接调用析构函数,你应该把它放到一个空的char缓冲区中。

相关问题