Python:喜欢的节点类中的内存泄漏

时间:2015-01-16 15:50:16

标签: python memory-leaks

我试图重新实现(再一次......我知道......)python中的一个简单网络,由引用其他节点类(他们的孩子)的节点类组成,我想知道如果会发生什么我创建了一个递归网络(node1 - > node2 - > node3 - > node1),并意外丢失了对任何节点的所有引用。

想象一下,我有以下代码

class node():
    def __init__(self):
        self.children = []

    def append(self, child):
        self.children.append(child)

node1 = node()
node2 = node()

node1.append(node2)
node2.append(node1) # now the network is recursive

node1 = 0
# node1 is still referenced in node2.children so will not be deleted
node2 = 0

# now both node1 and node2 are not directly referenced by any variable
# but they are referenced by the two children instances

在最后一行代码之后,对node1和node2的所有引用都将丢失,但最初分配给节点的内存包含对自身的引用。

node1和node2是否仍会被销毁?

1 个答案:

答案 0 :(得分:0)

是的,对象将被垃圾收集。垃圾收集器将检测循环引用并将其分解,以便可以进行正常的引用计数清理。请参阅gc module

如果您的node类实现了__del__方法并且您使用的是Python版本,那么出现问题3.4。在3.4中,现在大多数情况下都可以break circular references involving instances with __del__ methods

来自object.__del__ documentation

  

注意del x不直接调用x.__del__() - 前者将x的引用计数减1,后者仅在调用时调用x的引用计数达到零。可能阻止对象的引用计数变为零的一些常见情况包括:对象之间的循环引用(例如,双向链表或具有父指针和子指针的树数据结构);对捕获异常的函数的堆栈帧上的对象的引用(存储在sys.exc_traceback中的回溯使堆栈帧保持活动状态);或者在交互模式下引发未处理异常的堆栈帧上的对象的引用(存储在sys.last_traceback中的回溯使堆栈帧保持活动状态)。第一种情况只能通过明确打破周期来弥补;通过将None存储在sys.exc_tracebacksys.last_traceback中,可以解决后两种情况。启用选项周期检测器(默认情况下处于打开状态)时会检测到垃圾的循环引用,但只有在没有涉及Python级__del__()方法的情况下才能清除。有关如何通过循环检测器处理gc方法的详细信息,请参阅__del__()模块的文档,尤其是垃圾值的描述。