Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 来自dict析构函数的SEGFULT_Python_C++_Boost_Dictionary_Destructor - Fatal编程技术网

Python 来自dict析构函数的SEGFULT

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

我对基本对象析构函数boostpython有问题。 当在py_init范围内创建并销毁对象boost::python::dict时,一切都正常。 但在py_smth范围内,只有在本地dict desctructor被调用时,在构造函数执行之后,dict才被成功创建 打电话的时候我有分段错误

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