为什么将列表附加到其自身然后删除会导致内存泄漏

我找到了这个memory leak detection snippet,并且想知道它产生的内存泄漏。

import gc

def dump_garbage():
    """
    show us what's the garbage about
    """

    # force collection
    print("\nGARBAGE:")
    gc.collect()

    print("\nGARBAGE OBJECTS:")
    for x in gc.garbage:
        s = str(x)
        if len(s) > 80: s = s[:80]
        print(type(x),"\n  ",s)

if __name__=="__main__":
    import gc
    gc.enable()
    gc.set_debug(gc.DEBUG_LEAK)

    # make a leak
    l = []
    l.append(l)
    del l

    # show the dirt ;-)
    dump_garbage()

为了测试gc内存泄漏检测,作者创建了自己的小内存泄漏:

l = []
l.append(l)
del(l)

为什么会导致泄漏?如我所见,我将拥有一个列表对象,然后是一个嵌套列表对象,其中内部是外部,然后删除外部。 gc是否不知道要删除对原始列表的所有引用,从而导致内部列表泄漏?

haomeng228 回答:为什么将列表附加到其自身然后删除会导致内存泄漏

(将我之前的评论编辑成答案。)

链接的文章来自2001年。那时候,Python 2.x是新的,许多人可能仍在使用Python 1.x。

Python 1.x仅依靠引用计数来进行垃圾收集,而循环引用是失败时的教科书示例。 Python 2.x添加了一个循环检测步骤,但是仍然存在一些皱纹,例如存在__del__方法阻止垃圾收集器,因为它无法找出正确的销毁顺序。从Python 3.4开始,most of the wrinkles have been ironed out

那么为什么示例代码仍然指示泄漏?它设置了GC_DEBUG_LEAK标志,该标志尤其明确地告诉垃圾回收器将无法访问的对象保持在周围!

,

最有可能类似于无限循环: 在l = []l.append(l)期间,编译器在确定列表是[]还是[[]]还是[[[]]]时遇到了问题,因为列表是附加在其自身之后的。

希望您能理解它,您可以在这里看到我的shell示例:

>>> l = []
>>> l.append(l)
>>> l
[[...]]

#Then,again:

>>> l = []
>>> l.append(l)
>>> l.append(l)
>>> l

[[...],[...]]

>>> l[0],l[1]

([[...],[...]],[[...],[...]])

>>> l[0][0]

[[...],[...]]

>>> l[0][0][0]

[[...],[...]]    # and so on...

因此,您可以看到l基本上是无限列表,而删除无限列表将导致内存泄漏(我不知道原因,但是如果您想深入了解... )

希望这会有所帮助。

编辑
Shell会真正输出文本[...],以防万一。

本文链接:https://www.f2er.com/3168847.html

大家都在问