支持循环垃圾回收¶
Python 对检测和回收涉及循环引用的垃圾的支持,需要对象类型(这些对象类型是其他对象(也可能是容器)的“容器”)的支持。不存储对其他对象的引用,或仅存储对原子类型(如数字或字符串)的引用的类型,不需要为垃圾回收提供任何显式支持。
要创建容器类型,类型对象的 tp_flags
字段必须包含 Py_TPFLAGS_HAVE_GC
,并提供 tp_traverse
处理程序的实现。如果该类型的实例是可变的,则还必须提供 tp_clear
实现。
Py_TPFLAGS_HAVE_GC
设置此标志的类型对象必须符合此处记录的规则。为方便起见,这些对象将被称为容器对象。
容器类型的构造函数必须符合两条规则:
对象的内存必须使用
PyObject_GC_New
或PyObject_GC_NewVar
分配。一旦所有可能包含对其他容器引用的字段都已初始化,它必须调用
PyObject_GC_Track()
。
同样,对象的析构函数也必须符合类似的规则:
在引用其他容器的字段失效之前,必须调用
PyObject_GC_UnTrack()
。对象的内存必须使用
PyObject_GC_Del()
释放。警告
如果类型添加了 Py_TPFLAGS_HAVE_GC,则它 必须 至少实现一个
tp_traverse
处理程序,或显式使用其子类或超类中的处理程序。调用
PyType_Ready()
或间接调用它的某些 API(如PyType_FromSpecWithBases()
或PyType_FromSpec()
)时,如果类型继承自实现了垃圾回收协议的类,并且子类 不 包含Py_TPFLAGS_HAVE_GC
标志,则解释器将自动填充tp_flags
、tp_traverse
和tp_clear
字段。
-
PyObject_GC_New(TYPE, typeobj)¶
类似于
PyObject_New
,但用于设置了Py_TPFLAGS_HAVE_GC
标志的容器对象。不要直接调用此函数为对象分配内存;而是调用类型的
tp_alloc
槽位。填充类型的
tp_alloc
槽位时,PyType_GenericAlloc()
优先于仅调用此宏的自定义函数。此宏分配的内存必须使用
PyObject_GC_Del()
释放(通常通过对象的tp_free
槽位调用)。
-
PyObject_GC_NewVar(TYPE, typeobj, size)¶
类似于
PyObject_NewVar
,但用于设置了Py_TPFLAGS_HAVE_GC
标志的容器对象。不要直接调用此函数为对象分配内存;而是调用类型的
tp_alloc
槽位。填充类型的
tp_alloc
槽位时,PyType_GenericAlloc()
优先于仅调用此宏的自定义函数。此宏分配的内存必须使用
PyObject_GC_Del()
释放(通常通过对象的tp_free
槽位调用)。
-
PyObject *PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)¶
- 这是一个不稳定 API。它可能会在次要版本中未经警告而更改。
类似于
PyObject_GC_New
,但在对象末尾(偏移量tp_basicsize
处)分配 extra_size 字节。除了Python 对象头
之外,分配的内存初始化为零。额外数据将与对象一同释放,但除此之外,它不受 Python 管理。
此函数分配的内存必须使用
PyObject_GC_Del()
释放(通常通过对象的tp_free
槽位调用)。警告
此函数被标记为不稳定,因为实例之后保留额外数据的最终机制尚未确定。对于分配可变数量的字段,建议使用
PyVarObject
和tp_itemsize
。3.12 新版功能.
-
PyObject_GC_Resize(TYPE, op, newsize)¶
调整由
PyObject_NewVar
分配的对象的大小。返回类型为TYPE*
(指任何 C 类型) 的调整大小后的对象,失败时返回NULL
。op 必须是 PyVarObject* 类型,并且不能被垃圾回收器跟踪。newsize 必须是
Py_ssize_t
类型。
-
void PyObject_GC_Track(PyObject *op)¶
- 作为 稳定 ABI 的一部分。
将对象 op 添加到回收器跟踪的容器对象集合中。回收器可能在意外时间运行,因此对象在被跟踪时必须有效。这应该在
tp_traverse
处理程序跟随的所有字段都变得有效后调用,通常在构造函数的末尾附近。
-
int PyObject_GC_IsTracked(PyObject *op)¶
- 自 3.9 版本以来成为 稳定 ABI 的一部分。
如果 op 的对象类型实现了 GC 协议并且 op 当前正在被垃圾回收器跟踪,则返回 1,否则返回 0。
这类似于 Python 函数
gc.is_tracked()
。在 3.9 版本中新增。
-
int PyObject_GC_IsFinalized(PyObject *op)¶
- 自 3.9 版本以来成为 稳定 ABI 的一部分。
如果 op 的对象类型实现了 GC 协议并且 op 已经被垃圾回收器终结,则返回 1,否则返回 0。
这类似于 Python 函数
gc.is_finalized()
。在 3.9 版本中新增。
-
void PyObject_GC_Del(void *op)¶
- 作为 稳定 ABI 的一部分。
释放使用
PyObject_GC_New
或PyObject_GC_NewVar
分配给对象的内存。不要直接调用此函数来释放对象的内存;而是调用类型的
tp_free
槽位。不要将此函数用于由
PyObject_New
、PyObject_NewVar
或相关分配函数分配的内存;请改用PyObject_Free()
。参见
PyObject_Free()
是此函数的非 GC 等效函数。
-
void PyObject_GC_UnTrack(void *op)¶
- 作为 稳定 ABI 的一部分。
从回收器跟踪的容器对象集合中移除对象 op。请注意,可以再次对此对象调用
PyObject_GC_Track()
,将其重新添加到跟踪对象集合中。在tp_traverse
处理程序使用的任何字段失效之前,析构函数(tp_dealloc
处理程序)应该为此对象调用此函数。
3.8 版本发生变更: _PyObject_GC_TRACK()
和 _PyObject_GC_UNTRACK()
宏已从公共 C API 中移除。
tp_traverse
处理程序接受这种类型的函数参数:
-
typedef int (*visitproc)(PyObject *object, void *arg)¶
- 作为 稳定 ABI 的一部分。
传递给
tp_traverse
处理程序的访问器函数的类型。函数应以要遍历的对象作为 object,以及tp_traverse
处理程序的第三个参数作为 arg 调用。visit 函数不能以NULL
对象参数调用。如果 visit 返回非零值,则应立即返回该值。Python 核心使用多个访问器函数来实现循环垃圾检测;预计用户不需要编写自己的访问器函数。
tp_traverse
处理程序必须具有以下类型:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)¶
- 作为 稳定 ABI 的一部分。
容器对象的遍历函数。实现必须为 self 直接包含的每个对象调用 visit 函数,其中 visit 的参数是被包含对象和传递给处理程序的 arg 值。visit 函数不得使用
NULL
对象参数调用。如果 visit 返回非零值,则应立即返回该值。
为了简化编写 tp_traverse
处理程序,提供了 Py_VISIT()
宏。要使用此宏,tp_traverse
实现必须将其参数精确命名为 visit 和 arg
-
Py_VISIT(o)¶
如果 PyObject* o 不是
NULL
,则调用 visit 回调,参数为 o 和 arg。如果 visit 返回非零值,则返回该值。使用此宏,tp_traverse
处理程序如下所示:static int my_traverse(Noddy *self, visitproc visit, void *arg) { Py_VISIT(self->foo); Py_VISIT(self->bar); return 0; }
tp_clear
处理程序必须是 inquiry
类型,如果对象是不可变的,则为 NULL
。
-
typedef int (*inquiry)(PyObject *self)¶
- 作为 稳定 ABI 的一部分。
释放可能创建引用循环的引用。不可变对象不必定义此方法,因为它们永远不能直接创建引用循环。请注意,调用此方法后对象仍必须有效(不要只对引用调用
Py_DECREF()
)。如果回收器检测到此对象涉及引用循环,它将调用此方法。
控制垃圾回收器状态¶
C-API 提供了以下函数来控制垃圾回收运行。
-
Py_ssize_t PyGC_Collect(void)¶
- 作为 稳定 ABI 的一部分。
如果垃圾回收器已启用,则执行一次完整的垃圾回收。(请注意,
gc.collect()
会无条件运行它。)返回已收集 + 无法收集的不可达对象的数量。如果垃圾回收器已禁用或正在收集,则立即返回
0
。垃圾回收期间的错误将传递给sys.unraisablehook
。此函数不会引发异常。
-
int PyGC_Enable(void)¶
- 自 3.10 版本以来,作为 稳定 ABI 的一部分。
启用垃圾回收器:类似于
gc.enable()
。返回之前的状态,0 表示禁用,1 表示启用。在 3.10 版本加入。
-
int PyGC_Disable(void)¶
- 自 3.10 版本以来,作为 稳定 ABI 的一部分。
禁用垃圾回收器:类似于
gc.disable()
。返回之前的状态,0 表示禁用,1 表示启用。在 3.10 版本加入。
-
int PyGC_IsEnabled(void)¶
- 自 3.10 版本以来,作为 稳定 ABI 的一部分。
查询垃圾回收器的状态:类似于
gc.isenabled()
。返回当前状态,0 表示禁用,1 表示启用。在 3.10 版本加入。
查询垃圾回收器状态¶
C-API 提供了以下接口来查询有关垃圾回收器的信息。
-
void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)¶
- 这是一个不稳定 API。它可能会在次要版本中未经警告而更改。
对所有活动的、具备 GC 能力的对象运行提供的 callback。arg 会传递给 callback 的所有调用。
警告
如果回调函数分配(或释放)了新对象,则它们是否会被访问是未定义的。
操作期间垃圾回收被禁用。在回调函数中显式运行回收可能导致未定义的行为,例如多次访问相同的对象或根本不访问。
3.12 新版功能.
-
typedef int (*gcvisitobjects_t)(PyObject *object, void *arg)¶
要传递给
PyUnstable_GC_VisitObjects()
的访问器函数的类型。arg 与传递给PyUnstable_GC_VisitObjects
的 arg 相同。返回1
以继续迭代,返回0
以停止迭代。其他返回值目前保留,因此返回任何其他值的行为是未定义的。3.12 新版功能.