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

标签 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() 行修复此行为,但我认为有更正确的解决方案...

最佳答案

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

然后您将销毁该地址上的对象...然后您将再次销毁它。

这应该如何运作?

您要求的是 CSlot 对象的 vector ,所以这就是您得到的。您要求它的大小为 1,因此它包含一个 CSlot 对象,已完全构建并准备好进行操作。所以在它之上构造一个 CSlot 对象是没有意义的。

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

关于c++ - 为什么这个显式析构函数会导致共享 ptr 中的内存损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8666374/

相关文章:

c++ - 重新分配 boost::shared_array

valgrind - 抑制 Valgrind 中潜在的内存泄漏

c - valgrind 需要很长时间才能发现内存泄漏,但程序在没有 valgrind 的情况下运行需要几秒钟

调试由 valgrind 生成的内核

c++ - 如何在 C++ 中设置带参数的功能宏?

c++ - 从远程服务器接收垃圾字符?

引用变量的 C++ 初始化列表

c++ - 为纯虚析构函数添加定义的目的是什么?

C++ - 在基元上运行析构函数?

c++ - Mex 类内存泄漏 - STL 映射是否需要析构函数?