Python 来自dict析构函数的SEGFULT
我对基本对象析构函数boostpython有问题。 当在py_init范围内创建并销毁对象boost::python::dict时,一切都正常。 但在py_smth范围内,只有在本地dict desctructor被调用时,在构造函数执行之后,dict才被成功创建 打电话的时候我有分段错误Python 来自dict析构函数的SEGFULT,python,c++,boost,dictionary,destructor,Python,C++,Boost,Dictionary,Destructor,我对基本对象析构函数boostpython有问题。 当在py_init范围内创建并销毁对象boost::python::dict时,一切都正常。 但在py_smth范围内,只有在本地dict desctructor被调用时,在构造函数执行之后,dict才被成功创建 打电话的时候我有分段错误 class py_init { public: py_init::py_init() { Py_Initialize();
class py_init
{
public:
py_init::py_init()
{
Py_Initialize();
object main_module = import("__main__");
main_namespace = main_module.attr("__dict__");
main_namespace["sys"] = import("sys');
exec("sys.path.insert(0, "/foo/boo"), main_namespace, main_namespace);
}
object main_namespace;
};
class py_smth
{
public:
py_smth(std::shared_ptr<py_init> py)
{
dict local;
}
};
Backtrace:
Program terminated with signal SIGSEGV, Segmentation fault
#0 0x00007f501ddf9a38 in ?? () from /usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0
(gdb) bt
#0 0x00002b9545827a38 in ?? () from /usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0
#1 0x00002b95450ff12f in boost::python::api::object_base::~object_base() () from libplugin.so
#2 0x00002b95450ff060 in boost::python::api::object::~object() () from libplugin.so
#3 0x00002b9545101198 in boost::python::detail::dict_base::~dict_base() libplugin.so
#4 0x00002b9545101230 in boost::python::dict::~dict() libplugin.so
类py_init
{
公众:
py_init::py_init()
{
Py_初始化();
对象主模块=导入(“\uuuu主模块”);
main_namespace=main_module.attr(“u dict_u”);
main_名称空间[“sys”]=import(“sys”);
exec(“sys.path.insert(0,/foo/boo”)、主名称空间、主名称空间;
}
对象主名称空间;
};
类py_smth
{
公众:
py_-smth(标准::共享_-ptr-py)
{
dict局部;
}
};
回溯:
程序以信号SIGSEGV终止,分段故障
#0 0x00007f501ddf9a38英寸??()来自/usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0
(gdb)英国电信
#0 0x00002b9545827a38英寸??()来自/usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0
#libplugin.so中boost::python::api::object_base::~object_base()()中的1 0x00002b95450ff12f
#libplugin.so中boost::python::api::object::~object()()中的2 0x00002b95450ff060
#boost::python::detail::dict_base::~dict_base()libplugin.so中的3 0x00002b9545101198
#boost::python::dict::~dict()libplugin.so中的4 0x00002b9545101230
Libs版本:
-boost版本1.54
-python 3.4.2
我不知道为什么
嗯。这是不起作用的示例代码
main.cpp文件:
#include <iostream>
#include <boost/python.hpp>
#include <memory>
#include "smth.h"
using namespace boost::python;
class py_init
{
public:
py_init()
{
Py_Initialize();
object main_module = import("__main__");
main_namespace = main_module.attr("__dict__");
main_namespace["sys"] = import("sys");
main_namespace["time"] = import("time");
main_namespace["threading"] = import("threading");
exec("sys.path.insert(0, \"/foo/boo\")", main_namespace, main_namespace);
exec("def foo():print (\"bla\"); time.sleep(1);" , main_namespace, main_namespace);
exec("thread = threading.Thread(target=foo)" , main_namespace, main_namespace);
exec("thread.start()" , main_namespace, main_namespace);
state = PyEval_SaveThread();
}
~py_init()
{
PyEval_RestoreThread(state);
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
exec("thread.join()" , main_namespace, main_namespace);
PyGILState_Release(gstate);
std::cout<<"Py_init dest"<<std::endl;
}
object main_namespace;
PyThreadState* state;
};
int main()
{
std::shared_ptr<py_init> py(new py_init());
smth s(py);
s.print_foo();
return 0;
}
#包括
#包括
#包括
#包括“smth.h”
使用名称空间boost::python;
类py_init
{
公众:
py_init()
{
Py_初始化();
对象主模块=导入(“\uuuu主模块”);
main_namespace=main_module.attr(“u dict_u”);
main_名称空间[“sys”]=导入(“sys”);
main_名称空间[“time”]=导入(“time”);
main_名称空间[“threading”]=导入(“threading”);
exec(“sys.path.insert(0,\”/foo/boo\”),main\u名称空间,main\u名称空间);
exec(“def foo():print(\“bla\”);time.sleep(1);”,main\u名称空间,main\u名称空间);
exec(“thread=threading.thread(target=foo)”,main_名称空间,main_名称空间);
exec(“thread.start()”,main_名称空间,main_名称空间);
state=PyEval_SaveThread();
}
~py_init()
{
PyEval_RestoreThread(州);
皮吉州;
gstate=PyGILState_sure();
exec(“thread.join()”,main_名称空间,main_名称空间);
Pygilu状态释放(gstate);
std::cout程序正在调用未定义的行为,因为boost::python::dict
对象正在被不包含(GIL)的线程创建和销毁。如果线程正在执行任何影响python托管对象引用计数的操作,则它需要获取GIL。若要解决此问题,请在smth
构造函数中获取并释放GIL
smth::smth(std::shared_ptr py)
{
皮吉州;
gstate=PyGILState_sure();//获取GIL。
//持有GIL时,使用范围强制销毁。
{
boost::python::dict local;
}
Pygil状态_释放(gstate);//释放GIL。
}
可能值得考虑使用类来帮助管理GIL。例如,使用以下GIL_lock
类,当创建GIL_lock
对象时,调用线程将获取GIL。当GIL_lock
对象被破坏时,它将释放GIL
//@用于锁定和解锁GIL的简短RAII类。
吉鲁级锁
{
公众:
gil_lock(){state_u=PyGILState_sure();}
~gil_lock(){PyGILState_Release(state);}
私人:
皮吉州;
};
然后可以将smth
构造函数编写为:
smth::smth(std::shared_ptr py)
{
吉鲁锁;
boost::python::dict local;
}
这里是最小原始代码的注释版本。它强调调用方在py_init
的构造函数返回时不会持有GIL。因此,创建和销毁boost::python::dict
都会导致未定义的行为
类py_init
{
公众:
py_init()
{
Py_Initialize();//获取GIL(1)。
//…生成将竞争GIL的Python线程。
state=PyEval_SaveThread();//释放GIL(0)。
}
~py_init()
{
PyEval_RestoreThread(state);//获取GIL(1)。
皮吉州;
gstate=PyGILState_sure();//获取GIL(2)。
// ...
PyGILState_Release(gstate);//Release GIL(1)。
}
PyThreadState*状态;
};
int main()
{
std::shared_ptr py(新py_init());
//吉尔没有被抓住。
{
//在没有GIL的情况下修改对象;其他线程可能持有该对象。
boost::python::dict local;
}
}//~py_init()获得GIL。
在Python 3.4中,还可以使用函数检查调用线程是否持有GIL。根据文档,它主要是一个帮助器/诊断函数。对于早期版本,可以通过直接访问Python全局函数之一执行类似的检查:
\u PyThreadState\u Current==PyGILState\u gethisthreadstate();
该函数不能用于这种类型的诊断,因为如果没有线程持有GIL(这是一种有效状态),它会发出致命错误。观察SO的语法高亮显示,它清楚地表明您在那里提供的代码非常容易误导。我想知道这是否会编译……这是捕获当前情况的伪代码即使是伪代码,也不应该是。即使是,你真的认为伪代码在诊断SEGFULT时有用吗?我不知道你的情况,但至少我的伪代码很少出现SEGFULT。我添加了编译代码。也许现在你可以告诉我更多:)如果你使用
-std=c++11
,你能重现这个吗?
#ifndef SMTH_H_
#define SMTH_H_
#include <boost/python.hpp>
#include <memory>
using namespace boost::python;
class py_init;
class smth
{
public:
smth(std::shared_ptr<py_init> py)
{
dict local;
}
void print_foo()
{
std::cout<<"FOO"<<std::endl;
}
~smth()
{
std::cout<<"smth dest"<<std::endl;
}
};
#endif
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0 0x00007f9c5d787a38 in ?? () from /usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0 (gdb) bt
> #0 0x00007f9c5d787a38 in ?? () from /usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0
> #1 0x0000000000401a9d in boost::python::api::object_base::~object_base() ()
> #2 0x0000000000401922 in boost::python::api::object::~object() ()
> #3 0x0000000000401b50 in boost::python::detail::dict_base::~dict_base() ()
> #4 0x0000000000401bde in boost::python::dict::~dict() ()
> #5 0x0000000000401c08 in smth::smth(std::shared_ptr<py_init>) ()
> #6 0x0000000000401727 in main ()