diff options
author | Sam Gross <colesbury@gmail.com> | 2021-10-27 19:15:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-27 19:15:13 (GMT) |
commit | 35e1ff38ee67ee543d9fcb268c3552c5397f9b3f (patch) | |
tree | 4bcb6ac31c2957fb9c848193b37fca294d259ee5 | |
parent | 4776b07d178b2800374f5c15da182f1215756205 (diff) | |
download | cpython-35e1ff38ee67ee543d9fcb268c3552c5397f9b3f.zip cpython-35e1ff38ee67ee543d9fcb268c3552c5397f9b3f.tar.gz cpython-35e1ff38ee67ee543d9fcb268c3552c5397f9b3f.tar.bz2 |
bpo-28737: Document when tp_dealloc should call PyObject_GC_UnTrack() (GH-29246)
Objects that support garbage collection ("container" objects) should
call PyObject_GC_UnTrack() from their destructors before clearing any
fields which may point to other "container" objects.
-rw-r--r-- | Doc/c-api/gcsupport.rst | 16 | ||||
-rw-r--r-- | Doc/c-api/typeobj.rst | 12 | ||||
-rw-r--r-- | Doc/extending/newtypes.rst | 14 |
3 files changed, 33 insertions, 9 deletions
diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index 4bd2fb3..8c90d1e 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -33,6 +33,14 @@ Constructors for container types must conform to two rules: #. Once all the fields which may contain references to other containers are initialized, it must call :c:func:`PyObject_GC_Track`. +Similarly, the deallocator for the object must conform to a similar pair of +rules: + +#. Before fields which refer to other containers are invalidated, + :c:func:`PyObject_GC_UnTrack` must be called. + +#. The object's memory must be deallocated using :c:func:`PyObject_GC_Del`. + .. warning:: If a type adds the Py_TPFLAGS_HAVE_GC, then it *must* implement at least a :c:member:`~PyTypeObject.tp_traverse` handler or explicitly use one @@ -100,14 +108,6 @@ Constructors for container types must conform to two rules: .. versionadded:: 3.9 -Similarly, the deallocator for the object must conform to a similar pair of -rules: - -#. Before fields which refer to other containers are invalidated, - :c:func:`PyObject_GC_UnTrack` must be called. - -#. The object's memory must be deallocated using :c:func:`PyObject_GC_Del`. - .. c:function:: void PyObject_GC_Del(void *op) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index d3d23e1..5412879 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -668,6 +668,18 @@ and :c:type:`PyType_Type` effectively act as defaults.) :c:func:`PyObject_GC_Del` if the instance was allocated using :c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`. + If the type supports garbage collection (has the :const:`Py_TPFLAGS_HAVE_GC` + flag bit set), the destructor should call :c:func:`PyObject_GC_UnTrack` + before clearing any member fields. + + .. code-block:: c + + static void foo_dealloc(foo_object *self) { + PyObject_GC_UnTrack(self); + Py_CLEAR(self->ref); + Py_TYPE(self)->tp_free((PyObject *)self); + } + Finally, if the type is heap allocated (:const:`Py_TPFLAGS_HEAPTYPE`), the deallocator should decrement the reference count for its type object after calling the type deallocator. In order to avoid dangling pointers, the diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 6e17897..23ec8bc 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -73,7 +73,19 @@ function:: newdatatype_dealloc(newdatatypeobject *obj) { free(obj->obj_UnderlyingDatatypePtr); - Py_TYPE(obj)->tp_free(obj); + Py_TYPE(obj)->tp_free((PyObject *)obj); + } + +If your type supports garbage collection, the destructor should call +:c:func:`PyObject_GC_UnTrack` before clearing any member fields:: + + static void + newdatatype_dealloc(newdatatypeobject *obj) + { + PyObject_GC_UnTrack(obj); + Py_CLEAR(obj->other_obj); + ... + Py_TYPE(obj)->tp_free((PyObject *)obj); } .. index:: |