[C++-sig] copy boost::python::object crashes

Jim Bosch talljimbo at gmail.com
Mon Jan 25 02:32:12 CET 2010


On Sun, 2010-01-24 at 09:30 +0000, sergun wrote:
> I have changed setY function to:
> void setY(PyObject * y1) { y = object(handle<>(y1)); }
> 
> and it doesn’t make crash now.
> I’m not sure that such code has no problems and very interested to know why 
> assignment of one bp::object to another 
> is not correct. I suppose bp:object counteres references correctly and the 
> original object is killed only on Python.
> 

As it turns out, the new code is quite likely worse.  Here's what's
probably going on:

First, I should mention I get the segfault when quitting python after
running the python code, not after executing the last statement, so if
that's not what you experienced, there may be more going on.

Anyhow, with the original version, the global variable holds the only
reference to the Foo() object.  When Python exits, and the destructor
for the global variable executes, it DECREF's a Python object after a
lot of Python's machinery has already been shut down.  Interestingly, it
doesn't fail if you do setY("a string") or setY(5), but that's not much
consolation.

With the new version, the global variable ends up holding a Foo object
with ZERO reference count - I'm not sure, but I think it's already been
destroyed by the time the Python setY() call finishes, and the C++
global variable is just a ticking time bomb.  But since the reference
count is zero, nothing happens when the global's destructor goes off.

I think this all means it's probably a very bad idea to have a global or
class-static boost::python::object (or handle<>) variable.  The best
workaround I can think of right now is to have a a global PyObject*
instead, and do manual calls to Py_DECREF and Py_INCREF in the C++ setY
function.  That means the last thing left in the global will never get
destroyed, but unless it has a non-trivial Python destruct that
shouldn't matter.  If you need to make sure it gets destroyed, I think
you'll end up having to use Python's atexit.

Jim




More information about the Cplusplus-sig mailing list