2010-04-22 55 views
7

因此,我使用boost :: shared_ptr來提供它提供的各種引用計數優點 - 顯然對初學者有引用計數,但也有複製,分配和存儲在STL Containers中的能力。如何防止任何人竊取我的shared_ptr?

問題是,如果我將它傳遞給一個「惡意」函數或對象,對象可以保存ptr,然後如果沒有外函數或對象很好地放棄它,我將永遠無法取消它的分配所有權。

最終,我儘量保持對象所有權的明確。我通過讓所有者將唯一的shared_ptr保存到對象來實現這一點,而「guest」對象僅將weak_ptrs存儲到對象。

我真的不想shared_ptr的「共享」部分,但我需要使用shared_ptr來使weak_ptrs。我想使用scoped_ptr,但由於無法複製,所以它非常有限。您不能將其存儲在容器中,不能將weak_ptrs借出,並且無法將所有權轉讓給新的經理。

解決方案是什麼?

+0

這就是分享的問題,是不是:( – Cascabel 2010-04-22 06:03:00

+0

請注意,任何有'weak_ptr'的人都可以'鎖定'它,所以他們總是可以試圖竊取它,即使你永遠不會給他們所有權 – MSalters 2010-04-22 08:53:40

回答

1

正如您在討論中所描述的那樣,對訪客對象使用weak_ptr已經足夠了。否則,你會遇到死指針的問題。

我會考慮做應用程序rearchitect刪除「惡意」功能/對象或至少修復其行爲。

+0

事實證明,我控制所有的代碼,所以我最終刪除了「惡意」(或者我應該說「天真」)自己的代碼。我將繼續使用shared_ptrs,並且只要我可以使用weak_ptr就會更加小心,因爲我確實需要過期()檢查我真的很討厭這樣做,因爲我經常感覺自己是我自己最大的敵人,因爲當我打算s時意外保存shared_ptrs ave a weak_ptr。一般來說,這似乎是shared_ptrs的一個大問題,因爲它們通常比你想要的更粘。 – Kyle 2010-04-23 00:23:12

+0

接受這個答案是因爲這是我親自完成的工作,但它無法幫助控制代碼的任何人。感謝大家發佈他們的解決方案,他們都對我很好。我希望boost會出現'own_ptr'或其他東西... – Kyle 2010-04-26 15:26:57

10

讓它變得私密,並提供一個外觀來做任何需要的操作。沒有人看到指針。我想那時你甚至不需要shared_ptr。

+0

+1爲private,雖然這裏'shared_ptr'的明顯好處是能夠獲得'weak_ptr',這允許用戶知道原始對象是否仍然存在。 – 2010-04-22 06:18:18

0

您可以擴展shared_ptr boost類並覆蓋delete以強制刪除指針。

問題的確是,如果庫沒有釋放或釋放shared_ptr,那麼它可能會引用它一段時間。在這個時候你的應用程序將落入SIGSEGV。

我認爲這完全無效共享指針的目的。

最佳解決方案是修復庫。

其他解決方法,使用AOP刪除指定庫函數退出時指針。這仍然可能會打破。

4

不要傳遞boost :: shared_ptr對象......即使你使用boost :: shared_ptr在內部存儲對象,也應該確保函數通過常量引用而不是副本來引用對象的共享指針。由於您需要取消引用共享指針以將對象傳遞給通過const引用傳遞的函數,因此您將知道它是否遵循該協議。

+1

通過指針或引用傳遞對象的幾條經驗法則: a)僅當您想傳輸所有權時才傳遞純指針/自動指針(基本上是shared_ptr構造函數只有) b)如果被調用者必須保留訪問權限,不管怎樣,通過shared_ptr CONST引用或值(通過shared_ptr傳遞非const引用具有非常模糊的語義,如果你開始考慮它 - 只有當真正使用它時需要)。你可以通過將你的shared_ptr強制轉換爲const來保證在調用者方面。 c)在所有其他情況下,將(const)引用傳遞給對象。您也可以在打電話時保證這一點。 – 2010-04-22 08:59:02

0

對於您所描述的內容,確實沒有很好的解決方案。

由於您未轉讓所有權,您無法使用auto_ptr。

如果您可以保證擁有者超過了引用,我建議在所有者中使用scoped_ptr/store的值,然後將原始指針或引用傳遞給需要它的人。

如果引用超出所有者(並且引用需要得到適當的通知),則必須使用shared_ptr/weak_ptr。但是,正如你所說的,你不能阻止任何類/函數鎖定weak_ptr和「防止」重新分配。但是,在接口中,不要傳遞shared_ptr,傳遞weak_ptr。它只是像一個慣例一樣強大,但它說「不要拘泥於此,它可能會消失」。

0

如果你想處理你擁有的所有者/擁有範例中的對象,我建議你做一些類似Qt的事情。

  1. 創建一個基類Object,系統中的所有類都將繼承它。每個對象跟蹤其父/所有者和子女。
  2. 使用setOwner(Object * owner)方法來設置所有者,並讓該方法確保將所有者對象通知給新的孩子。
  3. Object的析構函數在銷燬時應刪除所有的子對象。
  4. 定義一個模板類,它定義了一個指向Object子類的智能指針。使對象通知所有連接的智能指針有關其銷燬,以便當對象被銷燬時,這些值將變爲NULL。

事情需要提防:

  1. 所有對象都必須通過新的對象被分配析構函數正確地取消分配它們。
  2. 如果您忘記設置對象的父級,它會泄漏
  3. 處理不從Object繼承的對象是棘手的,儘管可以通過定義一個繼承自Object的模板類來保存他們。
相關問題