2010-01-10 66 views
2

我有一個實現引用計數機制的對象。如果對其的引用數量變爲零,則刪除該對象。知道什麼是對象引用

我發現我的對象從不被刪除,即使當我完成它。這導致內存過度使用。我所擁有的是對象的引用數量,我想知道引用它的地方,以便我可以編寫適當的清理代碼。

有沒有辦法在不必grep源文件的情況下完成這個任務? (這將是非常繁瑣的。)

+0

最經典的故障:你有一個參考週期:x祝你好運! – 2010-01-10 16:04:26

回答

6

讓用C做正確的引用計數(引用計數)++的很大一部分是使用Resource Allocation Is Initialization所以它更難意外泄漏引用。但是,這並不能解決所有與refcounts有關的問題。

也就是說,你可以在你的refcounting中實現一個調試功能,跟蹤引用的內容。然後,您可以在必要時分析此信息,並將其從發佈版本中刪除。 (使用類似於如何使用DEBUG宏的配置宏)

具體如何實現它將取決於您的所有需求,但有兩種主要方法可以做到這一點(簡要概述差異):

  • 庫從調試器引用的對象本身
    • 訪問的信息
    • 更容易實現
  • 輸出到一個特殊的跟蹤文件中的每個的引用程序退出後獲得或釋放
    • 仍然可用時間(甚至是異常)
    • 可以使用,而在程序運行,而無需在調試器中運行
    • 甚至可以在特殊的發佈版本中使用,並送回給您分析

的基本問題,知道什麼是引用給定對象的,是h一般來說要解決,並且需要一些工作。比較:你能告訴我每個知道你的郵寄地址或電話號碼的人和企業嗎?

0

我不認爲有可能做一些事情,而無需更改代碼。通過更改代碼,您可以記住增加引用計數的對象的指針,然後查看剩下的指針並在調試器中對其進行檢查。如果可能的話 - 存儲更詳細的信息,例如對象名稱。

2

引用計數的一個已知弱點是,當存在循環引用時,即(最簡單的情況下),當一個對象引用了另一個對象,而該對象又引用了前一個對象時,它不起作用。這聽起來像是一個非問題,但在數據結構中,例如帶有對父節點的反向引用的二叉樹,就是這樣。

如果您沒有明確提供引用(未釋放)對象中的「反向」引用列表,我沒有看到找出引用它的人的方法。

在下面的建議中,我假設你不想修改你的源代碼,或者如果是這樣,只是一點點。

你當然可以走遍整個堆/ freestore並搜索未釋放對象的內存地址,但是如果其地址變爲up,則不能保證內存地址引用實際上是;它可以是任何隨機浮點數,也可以是其他任何浮點數。但是,如果發現的值位於塊的內部,則應用程序爲某個對象分配的內存會稍微提高,這確實是指向另一個對象的指針。

這種方法的一個可能的改進是修改你使用的內存分配器 - 例如,您的全球operator new - 以便它保留所有分配的內存塊及其大小的列表。 (在完整的實現中,operator delete將刪除釋放的內存塊的列表項。)現在,在程序結束時,您有一條線索,其中用於搜索未釋放對象的內存地址,因爲你有一個內存塊列表,你的程序實際上使用了

以上建議對我來說聽起來不太可靠,說實話;但也許定義一個自定義的全球operator newoperator delete,做一些記錄/追蹤去正確的方向來解決你的問題。

+2

有一天,一個學生來到月亮說:「我知道如何做一個更好的垃圾收集器,我們必須保留對每個缺點指針的引用計數。」月亮耐心地告訴學生以下故事:「有一天,一個學生來到月亮說,'我明白如何做一個更好的垃圾收集器......'」(http://www.serve.com/cmtan/buddhism/ Lighter/aikoans.html,http://en.wikipedia.org/wiki/Hacker_koan) – outis 2010-01-10 13:39:44

+0

最簡單的情況是一個對自身有引用的對象。 :)(這也不是一種病態的情況,考慮任何使用'delete this'的類。) – 2010-01-10 14:47:04

0

我已經爲我的需求創建了一個。您可以將您的代碼與此代碼進行比較,查看缺少的內容。這並不完美,但它應該適用於大多數情況。 http://sites.google.com/site/grayasm/autopointer

當我使用它我做的:

util::autopointer<A> aptr=new A(); 

我從來沒有像這樣做:

A* ptr = new A(); 
util::autopointer<A> aptr = ptr; 

,後來開始與PTR各地縮絨;這是不允許的。 此外,我僅使用aptr來引用此對象。 如果我錯了,我現在有機會得到更正。 :) 再見!

1

我假設你有一些類說addRef()release()成員函數,你調用這些當你需要增加或減少在每個實例的引用計數,而導致問題的情況下,是在堆上,並提到與生指針。最簡單的解決方法可能是用boost::shared_ptr替換受控對象的所有指針。這非常容易實現,並且應該使您可以省去自己的引用計數 - 您可以讓我提到的那些功能什麼都不做。代碼中所需的主要更改是在傳遞或返回指針的函數的簽名中。其他需要改變的地方是初始化列表(如果你初始化指針爲null)和if() - 語句(如果你比較指針爲null)。更改指針的聲明後,編譯器將查找所有這些地方。

如果你不想使用shared_ptr - 也許你想保持引用計數內在的類 - 你可以製作自己的簡單智能指針只是爲了處理你的課堂。然後用它來控制類對象的生命週期。因此,例如,您不需要使用原始指針進行指針分配,而是「手動」調用addRef(),您只需自動執行智能指針類的分配,其中包括addRef()

+1

使用管理資源作爲其自然生命的固有部分的對象稱爲RAII。 – 2010-01-10 13:57:39

+0

沒有合理的人會不同意這一點。 – Permaquid 2010-01-14 05:24:52

相關問題