]> granicus.if.org Git - python/commitdiff
Fix for SF bug 110688: Instance deallocation neglected to account for
authorTim Peters <tim.peters@gmail.com>
Sun, 17 Sep 2000 14:40:17 +0000 (14:40 +0000)
committerTim Peters <tim.peters@gmail.com>
Sun, 17 Sep 2000 14:40:17 +0000 (14:40 +0000)
that Py_INCREF boosts global _Py_RefTotal when Py_REF_DEBUG is defined
but Py_TRACE_REFS isn't.

There are, IMO, way too many preprocessor gimmicks in use for refcount
debugging (at least 3 distinct true/false symbols, but not all 8 combos
are supported by the code, etc etc), and no coherent documentation of
this stuff -- 'twas too painful to track this one down.

Objects/classobject.c

index d963fe13bbb9e7982dd7ceb257f3611d4ea0fa67..19059fccef31ca8d712f75985c5a088fc3b269be 100644 (file)
@@ -487,37 +487,52 @@ instance_dealloc(register PyInstanceObject *inst)
        PyObject *error_type, *error_value, *error_traceback;
        PyObject *del;
        static PyObject *delstr;
-#ifdef Py_TRACE_REFS
+#ifdef Py_REF_DEBUG
        extern long _Py_RefTotal;
 #endif
-       /* Call the __del__ method if it exists.  First temporarily
-          revive the object and save the current exception, if any. */
+       /* Temporarily resurrect the object. */
 #ifdef Py_TRACE_REFS
+#ifndef Py_REF_DEBUG
+#   error "Py_TRACE_REFS defined but Py_REF_DEBUG not."
+#endif
        /* much too complicated if Py_TRACE_REFS defined */
        inst->ob_type = &PyInstance_Type;
        _Py_NewReference((PyObject *)inst);
-       _Py_RefTotal--;         /* compensate for increment in NEWREF */
 #ifdef COUNT_ALLOCS
-       inst->ob_type->tp_alloc--; /* ditto */
+       /* compensate for boost in _Py_NewReference; note that
+        * _Py_RefTotal was also boosted; we'll knock that down later.
+        */
+       inst->ob_type->tp_alloc--;
 #endif
 #else /* !Py_TRACE_REFS */
+       /* Py_INCREF boosts _Py_RefTotal if Py_REF_DEBUG is defined */
        Py_INCREF(inst);
 #endif /* !Py_TRACE_REFS */
+
+       /* Save the current exception, if any. */
        PyErr_Fetch(&error_type, &error_value, &error_traceback);
+       /* Execute __del__ method, if any. */
        if (delstr == NULL)
                delstr = PyString_InternFromString("__del__");
        if ((del = instance_getattr2(inst, delstr)) != NULL) {
                PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);
-               if (res == NULL) {
+               if (res == NULL)
                        PyErr_WriteUnraisable(del);
-               }
                else
                        Py_DECREF(res);
                Py_DECREF(del);
        }
-       /* Restore the saved exception and undo the temporary revival */
+       /* Restore the saved exception. */
        PyErr_Restore(error_type, error_value, error_traceback);
-       /* Can't use DECREF here, it would cause a recursive call */
+       /* Undo the temporary resurrection; can't use DECREF here, it would
+        * cause a recursive call.
+        */
+#ifdef Py_REF_DEBUG
+       /* _Py_RefTotal was boosted either by _Py_NewReference or
+        * Py_INCREF above.
+        */
+       _Py_RefTotal--;
+#endif
        if (--inst->ob_refcnt > 0) {
 #ifdef COUNT_ALLOCS
                inst->ob_type->tp_free--;
@@ -525,14 +540,15 @@ instance_dealloc(register PyInstanceObject *inst)
                return; /* __del__ added a reference; don't delete now */
        }
 #ifdef Py_TRACE_REFS
+       _Py_ForgetReference((PyObject *)inst);
 #ifdef COUNT_ALLOCS
-       inst->ob_type->tp_free--;       /* compensate for increment in UNREF */
+       /* compensate for increment in _Py_ForgetReference */
+       inst->ob_type->tp_free--;
 #endif
-       _Py_ForgetReference((PyObject *)inst);
 #ifndef WITH_CYCLE_GC
        inst->ob_type = NULL;
 #endif
-#endif /* Py_TRACE_REFS */
+#endif
        PyObject_GC_Fini(inst);
        Py_DECREF(inst->in_class);
        Py_XDECREF(inst->in_dict);