`gc`是否与`__del__`类似地对待Cython的`__dealloc__`?

时间:2017-10-08 02:22:02

标签: python garbage-collection cython cyclic-reference

Python的可选垃圾收集器gc忽略contain any object with a __del__ method

的循环
  

版本3.4中更改:在PEP 442之后,使用__del__()方法的对象不再在gc.garbage中结束。

Cython扩展类型可以有__dealloc__方法,但no __del__ method

  

注意:扩展类型没有__del__()方法。

出于收集周期的目的,是否存在由垃圾收集器处理的__dealloc__,好像存在__del__方法一样?或者__dealloc__对垃圾收集器是不可见的吗?

1 个答案:

答案 0 :(得分:1)

如果查看生成的C代码,可以看到Cython在tp_dealloc插槽中生成析构函数,而不是tp_del插槽

cdef class B:
    def __dealloc__(self):
        pass

产生

static PyTypeObject __pyx_type_5cy_gc_B = {
  PyVarObject_HEAD_INIT(0, 0)
  "cy_gc.B", /*tp_name*/
  sizeof(struct __pyx_obj_5cy_gc_B), /*tp_basicsize*/
  0, /*tp_itemsize*/
  __pyx_tp_dealloc_5cy_gc_B, /*tp_dealloc*/

  /* lines omitted */

  0, /*tp_del*/
  0, /*tp_version_tag*/
  #if PY_VERSION_HEX >= 0x030400a1
  0, /*tp_finalize*/
  #endif
};

您也可以轻松验证其他示例的情况(例如,自动生成__dealloc__的类)。

Therefore, for Python 3.4+

  

从Python 3.4开始,这个列表大多数时候应该是空的,除非使用带有非NULL tp_del插槽的C扩展类型的实例。

Cython类不应该在这个无法收集的东西列表中结束,因为它们没有定义tp_del

对于早期版本的Python,我认为你也没关系。主要是因为你仍然没有__del__方法,而且因为cython automatically generates tp_traverse and tp_clear functions应该允许Python中断参考周期涉及Cython类。

您可以停用这些tp_traversetp_clear功能的生成。我有点不清楚参考周期中的对象会发生什么,但没有方法来检测它,或者打破它。它们很可能只是继续存在于某个地方,但却无法进入。

我认为关注(在Python 3.4之前)是__del__方法可以使对象再次可访问:

class C:
   def __del__(self):
      global x
      x = self
在不返回点之后调用

__dealloc__,因此不允许这样做(如果访问x,则只会出现分段错误)。因此,他们不必被gc.garbage置于不确定的状态。