链接节点 类 中的内存泄漏
Memory leaks in classes of linked nodes
我正在尝试在 python 中重新实现(再一次……我知道……)一个由节点 类 构成的简单网络,该节点引用其他节点 类(他们 children),我想知道如果我创建一个递归网络 (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还会被销毁吗?
是的,对象将被垃圾回收。垃圾收集器将检测循环引用并将其中断,以便可以进行正常的引用计数清理。见 gc
module.
如果您的 node
class 实现了 __del__
方法并且您使用的是 Python,您 将 遇到问题版本 < 3.4。在 3.4 中现在可以 break circular references involving instances with __del__
methods 在大多数情况下。
来自object.__del__
documentation:
Note: del x
doesn’t directly call x.__del__()
— the former decrements the reference count for x
by one, and the latter is only called when x
‘s reference count reaches zero. Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored in sys.exc_traceback
keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored in sys.last_traceback
keeps the stack frame alive). The first situation can only be remedied by explicitly breaking the cycles; the latter two situations can be resolved by storing None
in sys.exc_traceback
or sys.last_traceback
. Circular references which are garbage are detected when the option cycle detector is enabled (it’s on by default), but can only be cleaned up if there are no Python-level __del__()
methods involved. Refer to the documentation for the gc
module for more information about how __del__()
methods are handled by the cycle detector, particularly the description of the garbage value.
我正在尝试在 python 中重新实现(再一次……我知道……)一个由节点 类 构成的简单网络,该节点引用其他节点 类(他们 children),我想知道如果我创建一个递归网络 (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还会被销毁吗?
是的,对象将被垃圾回收。垃圾收集器将检测循环引用并将其中断,以便可以进行正常的引用计数清理。见 gc
module.
如果您的 node
class 实现了 __del__
方法并且您使用的是 Python,您 将 遇到问题版本 < 3.4。在 3.4 中现在可以 break circular references involving instances with __del__
methods 在大多数情况下。
来自object.__del__
documentation:
Note:
del x
doesn’t directly callx.__del__()
— the former decrements the reference count forx
by one, and the latter is only called whenx
‘s reference count reaches zero. Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored insys.exc_traceback
keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored insys.last_traceback
keeps the stack frame alive). The first situation can only be remedied by explicitly breaking the cycles; the latter two situations can be resolved by storingNone
insys.exc_traceback
orsys.last_traceback
. Circular references which are garbage are detected when the option cycle detector is enabled (it’s on by default), but can only be cleaned up if there are no Python-level__del__()
methods involved. Refer to the documentation for thegc
module for more information about how__del__()
methods are handled by the cycle detector, particularly the description of the garbage value.