2013-01-22 49 views
0

我正在C++中開發貝葉斯推理採樣器,它在樹上中繼很多,並且這個樹是在智能指針(Boost的shared_ptr和weak_ptr)的幫助下實現的。Boost shared_ptr不會立即銷燬對象

在推斷過程中(即運行一個長時間的C++函數1-2分鐘),樹被改變很多,創建並銷燬了許多節點。

完全推理過程(100%負載)佔用處理器(更精確地說,它是一個線程)。出於某種原因,新內存(對於新節點)正在被佔用,但舊內存不會被完全釋放,這會在內存溢出1-2分鐘後導致內存溢出。

雖然,如果我在推理過程中添加暫停,程序似乎完全銷燬舊對象,並且一切正常。

在我看來,原因是析構函數(或者更準確地說,它後面發生的事情,即內存釋放)由於某種原因而被延遲。

請問:請問: 1)這看起來是一個真正的問題嗎? 2)如果是,那麼等待「足夠的內存」被釋放時如何更好?什麼是標準策略?

(該程序正在被在Unix上運行。)

+3

對我來說,聽起來像你的shared_ptr仍然有引用持有給他們,因此不會被直接銷燬。但說實話,很難說沒有任何代碼。 –

+1

'shared_ptr'只是調用'delete'。你確定觀察到的行爲不是由於「刪除」?因爲'刪除'實現是已知的,它推遲了實際的處理,假設他們可以回收分配。 – MSalters

+0

MSalters,你可以給出一個關於刪除實現的信息,並推遲釋放嗎?我認爲這可能是我的情況。 (對不起,還沒有找到我自己。) –

回答

0

當指向對象的最後的shared_ptr被破壞,該對象被立即刪除。所以你聽起來很奇怪。我能想象的唯一想法就是你已經爲你的實現附加了一個垃圾收集器......否則,請檢查所有舊對象是否被破壞。

2

您觀察到的內存問題似乎並不位於C++本身。如果shared_ptr釋放它的內存,它會立即執行,而不是以某種延遲的方式。但是,您認爲合適的操作系統可能會延遲「真正」版本一段時間。像Windows的「任務管理器」這樣的程序看起來好像程序消耗的內存越來越多,而這只是操作系統爲您預留的內存,但實際上並不佔用您的內存。如果你的計算產生了如此巨大的處理器負載,那麼調度器可能會延遲相當「不重要」的任務(如釋放內存),直到有時間,以免妨礙計算等更重要的事情。

但是,釋放和分配內存很昂貴。而且你似乎可以自由分配大量的內存。你應該考慮通過做自己的內存管理(比如內存池等),或者通過回收對象(即節點)本身來回收那些內存,這意味着不會真的銷燬它們,而是將它們還給一些「節點池」並用新的值重新設置它們。兩者都可以與shared_ptr結合使用。

+0

謝謝!請問,如果不使用內存池概念,是否有任何方法可以(1)控制調度程序的優先級,以執行取消分配作爲第一優先級,(2)或者如果不可能調整調度程序,有多合理並優雅地暫停等待必要的釋放? –

1

聲音就像你在樹中有循環一樣,即它對子和父指針都使用shared_ptr,這可以防止自動樹節點的破壞。使用普通指針可能會更好。

+2

或者使用一個方向的強指針和另一個方向的弱指針。或者在刪除對象時手動斷開指針。 –

+0

@DavidSchwartz雖然它不比簡單的指針更簡單。 –

+0

通常不需要跟蹤刪除對象的安全時間就可以了。用我的兩種方法,你不需要。 –