python - Python 的垃圾收集器如何检测循环引用?

标签 python garbage-collection cpython

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

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

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

最佳答案

How does Python detect & free circular memory references before making use of the gc module?

它没有。 gc 仅存在 检测和释放循环引用。非循环引用通过引用计数处理。

现在,要了解 gc 如何确定任何给定对象引用的对象集,请查看 Modules/gcmodule.c 中的 gc_get_references 函数。相关位是:

// Where `obj` is the object who's references we want to find
traverseproc traverse;
if (! PyObject_IS_GC(obj))
    continue;
traverse = Py_TYPE(obj)->tp_traverse;
if (! traverse)
    continue;
if (traverse(obj, (visitproc)referentsvisit, result)) {
    Py_DECREF(result);
    return NULL;
}

这里的主要功能是tp_traverse。每个 C 级类型都定义了一个 tp_traverse 函数(或者对于不包含任何引用的对象,例如 str,将其设置为 NULL)。 tp_traverse 的一个例子是 list_traverselist 的遍历函数:

static int
list_traverse(PyListObject *o, visitproc visit, void *arg)
{
    Py_ssize_t i;

    for (i = Py_SIZE(o); --i >= 0; )
        Py_VISIT(o->ob_item[i]);
    return 0;
}

I see is a statement that circular references are detected, except when the objects involved have a __del__() method.

你是对的——Python 的循环检测器可以检测和收集循环除非它们包含带有 __del__ 方法的对象,因为解释器无法安全地删除这些对象(要直观了解这是为什么,假设您有两个对象,它们具有相互引用的 __del__ 方法。它们应该按什么顺序被释放?)。

当带有 __del__ 方法的对象参与循环时,垃圾收集器会将它们放入单独的列表中(可通过 gc.garbage 访问),以便程序员可以手动“处理”它们.

关于python - Python 的垃圾收集器如何检测循环引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10962393/

相关文章:

python - "Bad argument (train data must be floating-point matrix)"错误

python - 从打乱的 n-gram 列表中生成可能的句子(python)

python - PyPy:获取对字符串的原始访问

python - 循环 'for element in list_[a:b]' 是否使用解释器优化的未使用副本?

Python - 测试一个抽象基类

python - Django 相当于 Rails 的 x.days.from_now

c++ - 如何使用 C++11 的最小 gc 支持

garbage-collection - 为什么需要 3 次 Full GC 来对 permgen 进行垃圾回收?

java - Android:在实体调用 Finalize 时插入数据库

python - 为什么CPython在执行func(*iterable)时调用len(iterable)?