一般來說在 Python 中,為了解決內存泄漏問題,采用了對象引用計數,并基于引用計數實現自動垃圾回收。
由于Python 有了自動垃圾回收功能,就造成了不少初學者誤認為自己從此過上了好日子,不必再受內存泄漏的騷擾了。但如果仔細查看一下Python文檔對 __del__() 函數的描述,就知道這種好日子里也是有陰云的。下面摘抄一點文檔內容如下:
Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored in sys.exc_traceback keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored in sys.last_traceback keeps the stack frame alive).
可見,有 __del__() 函數的對象間的循環引用是導致內存泄漏的主兇。
另外需要說明:對沒有 __del__() 函數的 Python 對象間的循環引用,是可以被自動垃圾回收掉的。
如何知道一個對象是否內存泄漏了呢?
方法一、當你認為一個對象應該被銷毀時(即引用計數為 0),可以通過 sys.getrefcount(obj) 來獲取對象的引用計數,并根據返回值是否為 0 來判斷是否內存泄漏。如果返回的引用計數不為 0,說明在此刻對象 obj 是不能被垃圾回收器回收掉的。
方法二、也可以通過 Python 擴展模塊 gc 來查看不能回收的對象的詳細信息。
首先,來看一段正常的測試代碼:
#--------------- code begin --------------# -*- coding: utf-8 -*-import gcimport sysclass CGcLeak(object): def __init__(self): self._text = '#'*10 def __del__(self): passdef make_circle_ref(): _gcleak = CGcLeak()# _gcleak._self = _gcleak # test_code_1 print '_gcleak ref count0:%d' % sys.getrefcount(_gcleak) del _gcleak try: print '_gcleak ref count1:%d' % sys.getrefcount(_gcleak) except UnboundLocalError: print '_gcleak is invalid!'def test_gcleak(): # Enable automatic garbage collection. gc.enable() # Set the garbage collection debugging flags. gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | / gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS) print 'begin leak test...' make_circle_ref() print 'begin collect...' _unreachable = gc.collect() print 'unreachable object num:%d' % _unreachable print 'garbage object num:%d' % len(gc.garbage)if __name__ == '__main__': test_gcleak()
在 test_gcleak() 中,設置垃圾回收器調試標志后,再用 collect() 進行垃圾回收,最后打印出該次垃圾回收發現的不可達的垃圾對象數和整個解釋器中的垃圾對象數。
gc.garbage 是一個 list 對象,列表項是垃圾收集器發現的不可達(即是垃圾對象)、但又不能釋放(即不能回收)的對象。文檔描述為:A list of objects which the collector found to be unreachable but could not be freed (uncollectable objects).
新聞熱點
疑難解答