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

标签 python garbage-collection cython cyclic-reference

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

Changed in version 3.4: Following PEP 442, objects with a __del__() method don’t end up in gc.garbage anymore.

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

Note: There is no __del__() method for extension types.

出于收集循环的目的,垃圾收集器是否将 __dealloc__ 的存在视为存在 __del__ 方法?或者 __dealloc__ 对垃圾收集器不可见?

最佳答案

如果您查看生成的 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+ :

Starting with Python 3.4, this list should be empty most of the time, except when using instances of C extension types with a non-NULL tp_del slot.

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 中。

关于python - `gc` 对待 Cython 的 `__dealloc__` 是否与 `__del__` 类似?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46626961/

相关文章:

javascript - 使用 Python Flask 自定义 Stripe Checkout

python - Pandas.DataFrame.apply 返回 None 值

python - Selenium + Python : How to stop page loading when certain element gets loaded?

python - Cython:让python创建内存由C++填充

python - Cython:创建返回数组的 C 函数

python - 在 cython 中指定大于 long double 的数字

Python XML-获取两个节点之间的内容

c# - 垃圾收集器是否回收值类型内存

java - 并发模式失败的问题

c# - 具有内存压力的 SafeHandle