Почему этот явный деструктор вызывает повреждение памяти в общем ptr? - PullRequest
1 голос
/ 29 декабря 2011

Что не так с этим кодом и как я могу его исправить?

#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 Ответ

6 голосов
/ 29 декабря 2011

Потому что то, что вы делаете, не имеет смысла. Вы создаете объект, а затем ... создаете объект по тому же адресу.

Затем вы уничтожаете объект по этому адресу ... И затем вы уничтожаете его снова.

Как это должно работать?

Вы запросили вектор из CSlot объектов, так что это то, что вы получили. Вы просили, чтобы он имел размер 1, поэтому он содержит один CSlot объект, полностью построенный и готовый к действию. Так что нет смысла создавать объект CSlot поверх него.

Если вы хотите использовать размещение new и вызывать деструктор напрямую, вы должны сделать это в пустой буфер char.

...