简体   繁体   中英

boost-python3 program crashes on exit

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

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM