2011-12-29 5 views
1

Что не так с этим кодом и как его исправить?Почему этот явный деструктор вызывает повреждение памяти в общем 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; 
} 

этот код выглядит как работает, и печатает:

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(), но я думаю, что есть более правильное решение ...

ответ

6

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

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

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

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

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

+0

Я хочу создать несколько слотов со значениями по умолчанию и позже инициализировать с помощью места размещения новым, а иногда и сбросить с явным деструктором ... Может быть, мне нужен другой конструктор для shared_ptr –

+0

«Если вы хотите использовать новое место размещения и вызвать деструктор прямо, вы должны сделать это в пустой буфер символов. " Не совсем. Вы должны использовать правильно выровненную необработанную память. Но буфер символов в порядке, если вы убедитесь, что он правильно выровнен. –

+0

@SergeDundich: Я пытался сохранить его простым, и char [] является наиболее распространенным способом сделать это. ;) – jalf