我们可以删除引用循环对象并释放它的内存吗?
Can we delete reference cycle object and free its memory?
我阅读了有关垃圾回收的不同文章。他们说我们需要 gc
模块来清理引用循环对象。但是我们可以通过简单地使用 del 来进行清理吗?
例如,如果我执行以下操作,我是否成功释放了这个引用循环对象的内存?如果是,那我们为什么还需要 gc
模块呢?如果不是,那为什么不呢?
>>> x = [1, 2, 3]
>>> x.append(x) # create reference cycle
>>> print(x)
[1, 2, 3, [...]]
>>> sys.getrefcount(x)
3
>>> del x[3]
>>> print(x)
[1, 2, 3]
>>> sys.getrefcount(x)
2
>>> del x # reference count of x goes to 0!
cpython 是引用计数的。当对象引用计数变为零时,它将被删除——这是与导致减少的代码内联完成的。垃圾收集器在那里处理对象无法访问但其引用计数不为零的情况。并不是说每个循环引用都需要垃圾回收。引用的展开方式很重要。
>>> x = [1, 2, 3]
我们创建了一个列表并将其绑定到 x
。该列表本身只是内存中的一个匿名对象,但目前可以通过 x
访问。让我们调用实际对象 列表 .
>>> x.append(x) # create reference cycle
>>> print(x)
[1, 2, 3, [...]]
>>> sys.getrefcount(x)
3
此时,列表 引用了 x
、它自己的第 4 个元素和 getrefcount
参数(当函数 returns, 留下 2 个参考文献).
>>> del x[3]
del
实际上并没有删除东西。它解除绑定对象。在这种情况下,列表的 __delitem__
函数被称为解除绑定 列表 从它自己的第 4 个元素,留下一个引用。
>>> del x
这次 del
从 x
中解除 列表 的绑定,并从命名空间中删除 x
。引用计数变为零,列表 被删除。从未涉及垃圾收集器。
现在让我们混合起来。
>>> x = [1, 2, 3]
>>> x.append(x) # create reference cycle
我们有 2 个引用列表。不过这次只是
>>> del x
del
从 x
解除绑定 列表 并将其引用计数减至 1。这不足以删除 列表 。现在我们有一个问题。 列表不再分配给我们可以访问的任何变量。它不在 x
中,因为 x
不再存在。但它仍然在记忆中。这就是垃圾收集器试图解决的问题。
我们不能只使用 del
,因为没有变量可以执行 del
。
我阅读了有关垃圾回收的不同文章。他们说我们需要 gc
模块来清理引用循环对象。但是我们可以通过简单地使用 del 来进行清理吗?
例如,如果我执行以下操作,我是否成功释放了这个引用循环对象的内存?如果是,那我们为什么还需要 gc
模块呢?如果不是,那为什么不呢?
>>> x = [1, 2, 3]
>>> x.append(x) # create reference cycle
>>> print(x)
[1, 2, 3, [...]]
>>> sys.getrefcount(x)
3
>>> del x[3]
>>> print(x)
[1, 2, 3]
>>> sys.getrefcount(x)
2
>>> del x # reference count of x goes to 0!
cpython 是引用计数的。当对象引用计数变为零时,它将被删除——这是与导致减少的代码内联完成的。垃圾收集器在那里处理对象无法访问但其引用计数不为零的情况。并不是说每个循环引用都需要垃圾回收。引用的展开方式很重要。
>>> x = [1, 2, 3]
我们创建了一个列表并将其绑定到 x
。该列表本身只是内存中的一个匿名对象,但目前可以通过 x
访问。让我们调用实际对象 列表 .
>>> x.append(x) # create reference cycle
>>> print(x)
[1, 2, 3, [...]]
>>> sys.getrefcount(x)
3
此时,列表 引用了 x
、它自己的第 4 个元素和 getrefcount
参数(当函数 returns, 留下 2 个参考文献).
>>> del x[3]
del
实际上并没有删除东西。它解除绑定对象。在这种情况下,列表的 __delitem__
函数被称为解除绑定 列表 从它自己的第 4 个元素,留下一个引用。
>>> del x
这次 del
从 x
中解除 列表 的绑定,并从命名空间中删除 x
。引用计数变为零,列表 被删除。从未涉及垃圾收集器。
现在让我们混合起来。
>>> x = [1, 2, 3]
>>> x.append(x) # create reference cycle
我们有 2 个引用列表。不过这次只是
>>> del x
del
从 x
解除绑定 列表 并将其引用计数减至 1。这不足以删除 列表 。现在我们有一个问题。 列表不再分配给我们可以访问的任何变量。它不在 x
中,因为 x
不再存在。但它仍然在记忆中。这就是垃圾收集器试图解决的问题。
我们不能只使用 del
,因为没有变量可以执行 del
。