2011-12-29 64 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對象是沒有意義的。

如果您想使用placement new並直接調用析構函數,則應該將其放入一個空的char緩衝區中。

+0

我想創建一些插槽的默認值,後來初始化放置新和有時重置與顯式析構函數......也許我需要一個其他構造函數爲shared_ptr – 2011-12-29 10:17:26

+0

「如果你想使用placement new並調用析構函數直接,你應該把它寫入一個空的字符緩衝區。「不完全是。您必須使用正確對齊的原始內存。但是,如果確保它正確對齊,字符緩衝區就可以。 – 2011-12-29 10:18:14

+0

@SergeDundich:我試圖保持簡單,而char []是最常見的方法。 ;) – jalf 2011-12-29 10:19:22

相關問題