[Python-Dev] UNREF invalid object

Tim Peters tim.one@comcast.net
Sun, 09 Feb 2003 23:11:53 -0500


[Gustavo Niemeyer]
> I've been playing with the bz2module to remove the file inheritance, as
> requested. While doing so, I've got the "UNREF invalid object" error
> when trying to run PyObject_Del(), inside a dealloc function, on an
> object which is not "externally" accessible (it's part of the class
> structure only, and has obj->ob_refcnt == 1, as expected). I'll replace
> the PyObject_Del() by Py_DECREF() which fixes the problem and feels more
> elegant to me anyway.

It's not just more elegant, it's mandatory.  If you look at the expansion of
Py_DECREF, you'll find that it does all sorts of (necessary) things under
different build types.  In particular, under a debug build, calling
PyObject_Del() fails to unlink the object from the doubly-linked list of all
objects, and that's exactly the cause of an "UNREF invalid object" error.
Py_DECREF() instead arranges to call _Py_ForgetReference(), which (among
other things) does the unlinking in a debug build.  You *could* call all
that stuff yourself by hand, but then you'd need as much #ifdef pain as goes
into the expansion of Py_DECREF in order to get it all right.

> OTOH, I wouldn't like to get over the problem without knowing what's
> really happening.  Is this a common problem pattern?

Nope.  Everyone else <wink> calls PyObject_Del only on the "self" argument
to the type's tp_dealloc function (which is called *by* the expansion of
Py_DECREF(self), so self must not be subjected to a Py_DECREF again).
Everything else should go thru Py_DECREF, including contained objects.