【问题标题】:Garbage collector doesn't deallocate linked objects (Linked Lists memory leak)垃圾收集器不会释放链接对象(链接列表内存泄漏)
【发布时间】:2015-05-02 20:33:55
【问题描述】:

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

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 环境中跟踪对象时。对象不存在还为它们分配了内存。

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

知道为什么吗?

【问题讨论】:

  • 在上面的代码中,在del l[:] 之后,您的完整列表仍然可以通过bprev 引用访问。

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


【解决方案1】:

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

【讨论】:

  • 非常感谢,菜鸟错误=/
  • 还有什么遗漏吗?你接受了,然后又不接受了。
  • 是的,实际上,我查看了这个概念,它很好而且正确。然而,当我尝试将内存使用量降低几兆时,仍然有 300mgbs 的内存被分配了。
  • @SaadTalaat:我对此无能为力;你的具体问题这里我可以回答,但是你的内存泄漏问题一般我无法解决,而不是这个问题的上下文。请注意,进程中的内存分配不一定会立即下降,因为操作系统不愿意过多地移动分配(如果你不做太多,计算机的性能会更好),所以释放 100 万个对象并不一定立即导致内存占用下降。
  • 好吧,谢谢。我在谈论你的代码。不是我的内存泄漏问题。 :)
猜你喜欢
  • 2012-01-03
  • 2012-05-21
  • 2018-05-10
  • 2021-11-22
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 1970-01-01
相关资源
最近更新 更多