在开发项目的过程中,我一直在努力工作,我遇到了垃圾收集器无法解除链接列表甚至列表的问题。
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环境中的对象时。对象不存在但尚未为它们分配内存。
但是,只有在链接实例时才会出现此问题。如果某个实例没有引用彼此。垃圾收集器行为正常。
知道为什么吗?
答案 0 :(得分:2)
您可能已清除l
,但b
和prev
仍引用最后创建的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
。