Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python';垃圾收集器是否检测循环引用?_Python_Garbage Collection_Cpython - Fatal编程技术网

Python';垃圾收集器是否检测循环引用?

Python';垃圾收集器是否检测循环引用?,python,garbage-collection,cpython,Python,Garbage Collection,Cpython,我试图理解Python的垃圾收集器是如何检测循环引用的。当我查看文档时,我看到的只是一条语句,即检测到循环引用,除非所涉及的对象具有\uu del\uu方法 如果发生这种情况,我的理解(可能是错误的)是gc模块通过(我假设)遍历所有分配的内存并释放任何无法访问的块来充当故障保护 Python在使用gc模块之前如何检测和释放循环内存引用 Python在使用gc模块之前如何检测和释放循环内存引用 没有。gc的存在只是为了检测和释放循环引用。非循环引用通过refcounting处理 现在,要查看gc如

我试图理解Python的垃圾收集器是如何检测循环引用的。当我查看文档时,我看到的只是一条语句,即检测到循环引用,除非所涉及的对象具有
\uu del\uu
方法

如果发生这种情况,我的理解(可能是错误的)是gc模块通过(我假设)遍历所有分配的内存并释放任何无法访问的块来充当故障保护

Python在使用gc模块之前如何检测和释放循环内存引用

Python在使用gc模块之前如何检测和释放循环内存引用

没有。gc的存在只是为了检测和释放循环引用。非循环引用通过refcounting处理

现在,要查看gc如何确定任何给定对象引用的对象集,请查看
Modules/gcmodule.c
中的
gc\u get\u references
函数。相关比特是:

//其中'obj'是我们要查找的引用对象
遍历过程遍历;
如果(!PyObject_是_GC(obj))
继续;
导线=Py_型(obj)->tp_导线;
如果(!遍历)
继续;
if(遍历(obj,(visitproc)参考访问,结果)){
Py_DECREF(结果);
返回NULL;
}
这里的主要功能是
tp\u遍历
。每个C级类型定义一个
tp\u遍历
函数(如果对象不包含任何引用,如
str
,则将其设置为
NULL
)。
tp\u遍历
的一个例子是
list\u遍历
,它是
list
的遍历函数:

static int
列表遍历(PyListObject*o,visitproc-visit,void*arg)
{
Py_ssize_t i;
对于(i=Py_SIZE(o);--i>=0;)
Py_访问(o->ob_项目[i]);
返回0;
}
我看到的是一条语句,循环引用被检测到,除非所涉及的对象具有
\uu del\uu()
方法

您是对的-Python的周期检测器可以检测和收集周期,除非它们包含具有
\uu del\uu
方法的对象,因为解释器无法安全地删除这些对象(为了直观地了解原因,假设有两个对象具有相互引用的
\uu del\uu
方法。它们应该按什么顺序释放?)

当带有
\uuu del\uuu
方法的对象涉及到一个循环时,垃圾收集器将把它们放在一个单独的列表中(可通过访问),以便程序员可以手动“处理”它们

Python在使用gc模块之前如何检测和释放循环内存引用

Python的垃圾收集器(实际上不是
gc
模块,它只是垃圾收集器的Python接口)实现了这一点。因此,Python在使用垃圾收集器之前不会检测并释放循环内存引用

Python通常在大多数对象的引用计数达到零时释放它们。(我说“most”是因为它从不释放,例如,小整数或内部字符串。)在循环引用的情况下,这种情况永远不会发生,因此垃圾收集器会周期性地遍历内存并释放循环引用的对象


当然,这些都是特定于CPython的。其他Python实现有不同的内存管理(Jython=Java VM,IronPython=Microsoft.NET CLR)。

我想我在@SvenMarnich对原始问题的评论中找到了我想要的答案:

容器对象是可以保存对其他Python对象的引用的Python对象。列表、类、元组等是容器对象;整数、字符串等不是。因此,只有容器对象存在循环引用的风险

每个Python对象都有一个字段-*gc_ref*,对于非容器对象,它(我相信)被设置为NULL。对于容器对象,它被设置为等于引用它的非容器对象的数量

任何*gc_ref*计数大于1的容器对象(我本以为是0,但现在还可以?)都有非容器对象的引用。因此,它们是可访问的,并且不被认为是不可访问的内存岛

由已知可访问的对象(即我们刚刚识别为*gc_ref*计数大于1的对象)可访问的任何容器对象也不需要释放

其余的容器对象不可访问(彼此除外),应该释放它们

链接是否提供了更全面的解释
是到源代码的链接,其中有注释进一步解释循环引用检测背后的思想。但不保证收集包含循环引用的垃圾说。你能链接你所指的文档页面吗?这是我正在阅读的页面:我在链接页面上找不到许可证,所以我不确定是否可以将较长的文章从该页面复制到so。如果不复制内容,。我不会写摘要,所以请继续。顺便说一句,我找到了链接。还有其他链接没有o相关邮件列表线程。垃圾收集器的基本概念似乎没有改变。不完全准确。Python不会遍历内存并释放无法访问的对象。它遍历内存并检测引用周期,然后释放这些引用周期。它是否“遍历内存”?我以为它遍历了引用列表?(还是“遍历内存”)有我不熟悉的技术定义吗?)
gc
模块是循环垃圾收集器。它不仅是Python接口,也是实现。默认情况下,
gc
模块不在sys.modules中,而其他一些实现内置在Python中的模块则在sys.modules中,因此我假设
gc
模块就是实现。感谢您的更新。I在文档中,我看到了下面的语句:“