Reputation: 61
While porting program from boost-python2 to boost-python3, I came to situation, that boost program with embedded python3 crashes on exit, though same code built with python 2.7 works well. This case can be narrowed to following sample
#include <boost/python.hpp>
#include <stdio.h>
int main()
{
Py_InitializeEx(0);
boost::python::object modMath = boost::python::import("math");
boost::python::object cosFunc = modMath.attr("cos");
Py_Finalize();
}
It works well with python 2.7 but gives following backtrace with python 3.x:
Program received signal SIGSEGV, Segmentation fault.
PyObject_GC_Del (op=0x7ffff6f134f0) at ../Modules/gcmodule.c:2313
2313 ../Modules/gcmodule.c: Нет такого файла или каталога.
(gdb) bt
#0 PyObject_GC_Del (op=0x7ffff6f134f0) at ../Modules/gcmodule.c:2313
#1 0x0000555555555366 in _Py_DECREF (op=0x7ffff6f134f0) at /usr/include/python3.9/object.h:430
#2 0x0000555555555469 in boost::python::api::object_base::~object_base (this=0x7fffffffde78, __in_chrg=<optimized out>) at /usr/include/boost/python/object_core.hpp:423
#3 0x00005555555553a8 in boost::python::api::object::~object (this=0x7fffffffde78, __in_chrg=<optimized out>) at /usr/include/boost/python/object_core.hpp:238
#4 0x0000555555555244 in main () at test3x_tb.cpp:12
Upvotes: 1
Views: 344
Reputation: 61
For some reason you should clean all your non trivial boost::python::object
s before calling Py_Finalize()
. For example this sample will work:
int main()
{
Py_InitializeEx(0);
{
boost::python::object modMath = boost::python::import("math");
boost::python::object cosFunc = modMath.attr("cos");
}
Py_Finalize();
}
Here destructors for both boost::python::object
s are called at the end of their scope, and when program reaches Py_Finalize()
they no longer exist. In your example boost::python::object
s destructors are called after Py_Finalize()
, and this causes trouble. So putting them in narrower scope it a good idea.
If for some reason you need to keep boost::python::object
s in global variable, you can replace their values with empty python objects right before calling Py_Finalize()
, this will call destructor for old value, and problem will be also solved.
boost::python::object cosFunc;
boost::python::object modMath;
int main()
{
Py_InitializeEx(0);
modMath = boost::python::import("math");
cosFunc = modMath.attr("cos");
/* Do whatever you need */
modMath = boost::python::object();
cosFunc = boost::python::object();
Py_Finalize();
}
Upvotes: 1