bpo-28737: Document when tp_dealloc should call PyObject_GC_UnTrack()… · python/cpython@35e1ff3 (original) (raw)
3 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -33,6 +33,14 @@ Constructors for container types must conform to two rules: | ||
33 | 33 | #. Once all the fields which may contain references to other containers are |
34 | 34 | initialized, it must call :c:func:`PyObject_GC_Track`. |
35 | 35 | |
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 | + | |
36 | 44 | .. warning:: |
37 | 45 | If a type adds the Py_TPFLAGS_HAVE_GC, then it *must* implement at least |
38 | 46 | a :c:member:`~PyTypeObject.tp_traverse` handler or explicitly use one |
@@ -100,14 +108,6 @@ Constructors for container types must conform to two rules: | ||
100 | 108 | |
101 | 109 | .. versionadded:: 3.9 |
102 | 110 | |
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 | - | |
111 | 111 | |
112 | 112 | .. c:function:: void PyObject_GC_Del(void *op) |
113 | 113 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -668,6 +668,18 @@ and :c:type:`PyType_Type` effectively act as defaults.) | ||
668 | 668 | :c:func:`PyObject_GC_Del` if the instance was allocated using |
669 | 669 | :c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`. |
670 | 670 | |
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 | + | |
671 | 683 | Finally, if the type is heap allocated (:const:`Py_TPFLAGS_HEAPTYPE`), the |
672 | 684 | deallocator should decrement the reference count for its type object after |
673 | 685 | calling the type deallocator. In order to avoid dangling pointers, the |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -73,7 +73,19 @@ function:: | ||
73 | 73 | newdatatype_dealloc(newdatatypeobject *obj) |
74 | 74 | { |
75 | 75 | 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); | |
77 | 89 | } |
78 | 90 | |
79 | 91 | .. index:: |