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

Ind*_*ant 1 c++ valgrind destructor explicit-constructor shared-ptr

这段代码有什么问题,如何解决?

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

ctor CTest
1
ctor CTest
dtor CTest
2
Run Code Online (Sandbox Code Playgroud)

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

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

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

jal*_*alf 6

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

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

这应该怎么样?

你问了一个CSlot对象的矢量,这就是你得到的.你要求它的大小为1,所以它包含一个CSlot完全构造并准备好行动的对象.因此,CSlot在它上面构造一个对象是没有意义 的.

如果要使用placement new并直接调用析构函数,则应将其放入空char缓冲区.

  • @工业 - 抗抑郁药:那是邪恶的.你通常只想拥有*one*对象,可以随意修改.摧毁由向量创建的那个,然后创建自己的只是讨厌.如果要重置它,请向该类添加一个重置成员函数,或执行如下赋值:`testVector [0] = CSlot()` (2认同)