垃圾收集器不释放链接对象(链接列表内存泄漏)

Garbage collector doesn't deallocate linked objects (Linked Lists memory leak)

在我一直致力于的项目开发过程中,我遇到了垃圾收集器无法取消分配链表甚至列表的问题。

class B(object):
    def __init__(self, previous):
        self.previous = previous
    def __del__(self):
        self.previous = None
        self = None
import gc
gc.set_debug(gc.DEBUG_LEAK)
l = []
prev = None
for i in range(1000000):
    b = B(prev)
    l.append(b)
    prev = b

del l[:]
gc.collect()
print gc.garbage

当我检查分配前、分配后和删除后的内存使用情况时。分配后的内存使用量仍然与删除后的内存使用量相同。并且垃圾收集器不会抱怨任何内存泄漏。

当我在python环境中使用pympler跟踪对象时。对象不存在但已为它们分配了内存。

但是,只有在链接实例时才会出现此问题。如果一个实例没有相互引用。垃圾收集器运行正常。

知道为什么吗?

您可能已经清除了 l,但 bprev 仍然引用最后创建的 B 实例。反过来,该实例指的是先前创建的实例,等等。保持整个链条活动:

>>> class B(object):
...     def __init__(self, previous):
...         self.previous = previous
...     def __del__(self):
...         self.previous = None
...         self = None
... 
>>> l = []
>>> prev = None
>>> for i in range(1000000):
...     b = B(prev)
...     l.append(b)
...     prev = b
... 
>>> del l[:]
>>> prev
<__main__.B object at 0x11f269d50>
>>> b
<__main__.B object at 0x11f269d50>
>>> b.previous
<__main__.B object at 0x11f269d10>
>>> import gc
>>> sum(1 for ob in gc.get_objects() if isinstance(ob, B))
1000000
>>> del b, prev
>>> sum(1 for ob in gc.get_objects() if isinstance(ob, B))
0

如果有 循环 引用,gc.garbage 列表只会列出 B 个实例;例如如果链中的最后一个 B 实例引用了同一链中的另一个实例,而不是 None.