1

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

1 Answer 1

1

For some reason you should clean all your non trivial boost::python::objects 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::objects are called at the end of their scope, and when program reaches Py_Finalize() they no longer exist. In your example boost::python::objects 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::objects 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();
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.