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

时间:2015-03-02 13:13:24

标签: python python-2.7 memory-leaks garbage-collection

在开发项目的过程中,我一直在努力工作,我遇到了垃圾收集器无法解除链接列表甚至列表的问题。

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

当我在分配之前和分配之后以及删除之后检查内存使用情况时。分配后的内存使用量仍与删除后的内存使用量相同。垃圾收集器并没有抱怨任何内存泄漏。

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

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

知道为什么吗?

1 个答案:

答案 0 :(得分:2)

您可能已清除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