Skip to content

Commit 193504a

Browse files
bpo-28737: Document when tp_dealloc should call PyObject_GC_UnTrack() (GH-29246) (GH-29248)
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. (cherry picked from commit 35e1ff3) Co-authored-by: Sam Gross <[email protected]>
1 parent 8e5e74e commit 193504a

File tree

3 files changed

+33
-9
lines changed

3 files changed

+33
-9
lines changed

Doc/c-api/gcsupport.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ Constructors for container types must conform to two rules:
3333
#. Once all the fields which may contain references to other containers are
3434
initialized, it must call :c:func:`PyObject_GC_Track`.
3535

36+
Similarly, the deallocator for the object must conform to a similar pair of
37+
rules:
38+
39+
#. Before fields which refer to other containers are invalidated,
40+
:c:func:`PyObject_GC_UnTrack` must be called.
41+
42+
#. The object's memory must be deallocated using :c:func:`PyObject_GC_Del`.
43+
3644
.. warning::
3745
If a type adds the Py_TPFLAGS_HAVE_GC, then it *must* implement at least
3846
a :c:member:`~PyTypeObject.tp_traverse` handler or explicitly use one
@@ -100,14 +108,6 @@ Constructors for container types must conform to two rules:
100108
101109
.. versionadded:: 3.9
102110
103-
Similarly, the deallocator for the object must conform to a similar pair of
104-
rules:
105-
106-
#. Before fields which refer to other containers are invalidated,
107-
:c:func:`PyObject_GC_UnTrack` must be called.
108-
109-
#. The object's memory must be deallocated using :c:func:`PyObject_GC_Del`.
110-
111111
112112
.. c:function:: void PyObject_GC_Del(void *op)
113113

Doc/c-api/typeobj.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,18 @@ and :c:type:`PyType_Type` effectively act as defaults.)
657657
:c:func:`PyObject_GC_Del` if the instance was allocated using
658658
:c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`.
659659

660+
If the type supports garbage collection (has the :const:`Py_TPFLAGS_HAVE_GC`
661+
flag bit set), the destructor should call :c:func:`PyObject_GC_UnTrack`
662+
before clearing any member fields.
663+
664+
.. code-block:: c
665+
666+
static void foo_dealloc(foo_object *self) {
667+
PyObject_GC_UnTrack(self);
668+
Py_CLEAR(self->ref);
669+
Py_TYPE(self)->tp_free((PyObject *)self);
670+
}
671+
660672
Finally, if the type is heap allocated (:const:`Py_TPFLAGS_HEAPTYPE`), the
661673
deallocator should decrement the reference count for its type object after
662674
calling the type deallocator. In order to avoid dangling pointers, the

Doc/extending/newtypes.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,19 @@ function::
7373
newdatatype_dealloc(newdatatypeobject *obj)
7474
{
7575
free(obj->obj_UnderlyingDatatypePtr);
76-
Py_TYPE(obj)->tp_free(obj);
76+
Py_TYPE(obj)->tp_free((PyObject *)obj);
77+
}
78+
79+
If your type supports garbage collection, the destructor should call
80+
:c:func:`PyObject_GC_UnTrack` before clearing any member fields::
81+
82+
static void
83+
newdatatype_dealloc(newdatatypeobject *obj)
84+
{
85+
PyObject_GC_UnTrack(obj);
86+
Py_CLEAR(obj->other_obj);
87+
...
88+
Py_TYPE(obj)->tp_free((PyObject *)obj);
7789
}
7890

7991
.. index::

0 commit comments

Comments
 (0)