简体   繁体   中英

Why does this explicit destructor cause memory corruption in a shared ptr?

What is wrong with this code and how can I fix it?

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

this code looks like working, and prints:

ctor CTest
1
ctor CTest
dtor CTest
2

but sometimes the program crash and valgrind always says:

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

I can fix this behavior with the m_test.reset() line, but I think there is a more correct solution...

Because what you're doing makes no sense. You're creating an object, and then... creating an object on the same address.

Then you're destroying the object on that address... And then you're destroying it again.

How is that supposed to work?

You asked for a vector of CSlot objects, so that's what you got. You asked for it to have size 1, so it contains one CSlot object, fully constructed and ready for action. So it doesn't make sense to construct a CSlot object on top of it.

If you want to use placement new and call the destructor directly, you should do it into an empty char buffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM