summaryrefslogtreecommitdiffstats
path: root/Objects/tupleobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/tupleobject.c')
-rw-r--r--Objects/tupleobject.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 3e3aea4..e64b93b 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -6,6 +6,7 @@
#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_object.h" // _PyObject_GC_TRACK()
+#include "pycore_pyerrors.h" // _Py_FatalRefcountError()
/*[clinic input]
class tuple "PyTupleObject *" "&PyTuple_Type"
@@ -287,6 +288,17 @@ tupledealloc(PyTupleObject *op)
}
#endif
}
+#if defined(Py_DEBUG) && PyTuple_MAXSAVESIZE > 0
+ else {
+ assert(len == 0);
+ struct _Py_tuple_state *state = get_tuple_state();
+ // The empty tuple singleton must only be deallocated by
+ // _PyTuple_Fini(): not before, not after
+ if (op == state->free_list[0] && state->numfree[0] != 0) {
+ _Py_FatalRefcountError("deallocating the empty tuple singleton");
+ }
+ }
+#endif
Py_TYPE(op)->tp_free((PyObject *)op);
#if PyTuple_MAXSAVESIZE > 0
@@ -1048,11 +1060,16 @@ _PyTuple_Fini(PyInterpreterState *interp)
struct _Py_tuple_state *state = &interp->tuple;
// The empty tuple singleton must not be tracked by the GC
assert(!_PyObject_GC_IS_TRACKED(state->free_list[0]));
+
+#ifdef Py_DEBUG
+ state->numfree[0] = 0;
+#endif
Py_CLEAR(state->free_list[0]);
- _PyTuple_ClearFreeList(interp);
#ifdef Py_DEBUG
state->numfree[0] = -1;
#endif
+
+ _PyTuple_ClearFreeList(interp);
#endif
}