c++ - unique_ptr - std:: shared_ptr memory leak




在模塊(exes和dll)之間使用STL(TR1)shared_ptr是否安全? (4)

我知道在一個模塊中新建一個模塊並在另一個模塊中刪除它往往會導致VC ++中的問題。 不同運行時間的問題。 混合使用靜態鏈接的運行時和/或動態鏈接的版本不匹配的模塊都可以把事情搞砸了,如果我沒有記錯的話。

但是,跨模塊使用VC ++ 2008的std :: tr1 :: shared_ptr是否安全?

由於只有一個版本的運行時甚至知道什麼是shared_ptr,靜態鏈接是我唯一的危險(現在...)。 我以為我讀過boost的版本的shared_ptr是可以安全使用的,但是我正在使用Redmond的版本...

我試圖避免有一個特殊的電話來釋放分配模塊中的對象。 (或類似於類中的“刪除”)。 如果這一切似乎有點哈克,我使用這個單元測試。 如果你曾經試過對現有的C ++代碼進行單元測試,你可以了解你有時需要多麼有創意 。 我的內存是由一個EXE分配的,但最終將被釋放在一個DLL中(如果引用計數按我認為的方式工作)。



我在總的主題上看到的最好的建議是內存應該被分配在相同的上下文中。 這並不妨礙一個庫傳遞一個應用程序代碼應該釋放的指針,所以我會說你可能安全地以這種方式傳遞shared_ptr,因為這是一般的情況。

如果你的系統的語義意味著指針實際上是從你的exe文件傳遞給你的dll,那麼auto_ptr可能是一個更好的解決方案。 但是,如果您的指針是真正共享的,那麼shared_ptr可能是最好的解決方案。


釋放內存是安全的,只要它們來自相同的內存管理環境。 你已經確定了最常見的問題(不同的C ++運行時)。 單獨的堆是另一個不太常見的問題,你可以碰到。

另一個你沒有提到但是可以被共享指針所誇大的問題是,當一個對象的代碼存在於DLL中並由DLL創建時,而DLL之外的另一個對象最終引用它(通過共享指針)。 如果在卸載DLL之後該對像被銷毀(例如,如果它是一個模塊級別的靜態,或者該DLL由FreeLibrary()顯式卸載,共享對象的析構函數將會崩潰。

如果您嘗試編寫基於DLL的,鬆散耦合的插件,可能會咬你。 這也是COM允許DLL決定什麼時候可以卸載的原因,而不是讓COM服務器卸載它們。


你開始看到令人難以置信的shared_ptr是多麼:)

跨越DLL邊界是安全的,正是shared_ptr被設計為(當然還有其他的東西)。

與其他人所說的相反,在構建shared_ptr ,甚至不需要傳遞定制的刪除器,因為默認情況已經是類似

template <typename T>
struct default_deleter {
    void operator()( T * t ) { delete t; }
};

shared_ptr<Foo> foo( new Bar );

相當於

shared_ptr<Foo> foo( new Bar, default_deleter<Bar>() );

(也就是說,沒有刪除器的情況下不存在shared_ptr這樣的事情)。

由於在刪除器上執行的類型delete ,被調用的delete始終是來自實例化 shared_ptr的DLL的delete ,而不是來自最後一個shared_ptr超出作用域的DLL的那個(即,調用刪除器的shared_ptr將通過一個指向原來的shared_ptr放在那裡的函數的指針來調用它)。

將它與auto_ptr比較, auto_ptrdelete操作符直接嵌入到它的(內聯)析構函數中,這意味著使用銷毀 auto_ptr的DLL的delete操作,從而產生與刪除裸指針相同的問題。

通過相同的技術,總是保存在shared_ptr的多態類甚至不需要虛擬析構函數,因為即使當最後一個shared_ptr超出作用域時,刪除器也會始終調用正確的析構函數, 。





shared-ptr