Skip to content

Commit 35e1ff3

Browse files
authored
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.
1 parent 4776b07 commit 35e1ff3

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
@@ -668,6 +668,18 @@ and :c:type:`PyType_Type` effectively act as defaults.)
668668
:c:func:`PyObject_GC_Del` if the instance was allocated using
669669
:c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`.
670670

671+
If the type supports garbage collection (has the :const:`Py_TPFLAGS_HAVE_GC`
672+
flag bit set), the destructor should call :c:func:`PyObject_GC_UnTrack`
673+
before clearing any member fields.
674+
675+
.. code-block:: c
676+
677+
static void foo_dealloc(foo_object *self) {
678+
PyObject_GC_UnTrack(self);
679+
Py_CLEAR(self->ref);
680+
Py_TYPE(self)->tp_free((PyObject *)self);
681+
}
682+
671683
Finally, if the type is heap allocated (:const:`Py_TPFLAGS_HEAPTYPE`), the
672684
deallocator should decrement the reference count for its type object after
673685
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)