Hello! 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. OTOH, I wouldn't like to get over the problem without knowing what's really happening. Is this a common problem pattern? Thanks! -- Gustavo Niemeyer [ 2AAC 7928 0FBF 0299 5EB5 60E2 2253 B29A 6664 3A0C ]
[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.
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.
Hummm... I thought PyObject_Del could be safely used when the object was "private". Ok, I'll investigate what Py_DECREF really does, and why it breaks if PyObject_Del is used.
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>
Ok.. I should have asked "is this something obviously stupid?" instead. :-))
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.
This paragraph looks like a good documentation to put somewhere. Thanks for explaining. -- Gustavo Niemeyer [ 2AAC 7928 0FBF 0299 5EB5 60E2 2253 B29A 6664 3A0C ]
participants (2)
-
Gustavo Niemeyer
-
Tim Peters