[Python-checkins] bpo-28737: Document when tp_dealloc should call PyObject_GC_UnTrack() (GH-29246)

ambv webhook-mailer at python.org
Wed Oct 27 15:15:26 EDT 2021


https://github.com/python/cpython/commit/35e1ff38ee67ee543d9fcb268c3552c5397f9b3f
commit: 35e1ff38ee67ee543d9fcb268c3552c5397f9b3f
branch: main
author: Sam Gross <colesbury at gmail.com>
committer: ambv <lukasz at langa.pl>
date: 2021-10-27T21:15:13+02:00
summary:

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.

files:
M Doc/c-api/gcsupport.rst
M Doc/c-api/typeobj.rst
M Doc/extending/newtypes.rst

diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst
index 4bd2fb3837a1a..8c90d1e8991c1 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 d3d23e1cf2ee3..541287956f0a5 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 6e17897ed2c80..23ec8bce8c5ac 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::



More information about the Python-checkins mailing list