垃圾收集器不释放链接对象(链接列表内存泄漏)
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
,但 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
.
在我一直致力于的项目开发过程中,我遇到了垃圾收集器无法取消分配链表甚至列表的问题。
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
,但 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
.