Python垃圾收集在破坏C ++对象时会导致SegFault

时间:2014-06-09 18:44:35

标签: boost-python

我有一个内部C ++库,我已经使用Boost.Python成功地向Python公开了这个库。它接受用户创建的Python对象,然后在该对象中使用某些方法来执行某些任务,并且它在大多数情况下都能正常工作。

该库的Python使用如下:

class Foo(object):

    def __init__(self, args):
        """create an instance of this class with instance-specific attributes"""

    def Bar1(self, a, b, c):
        """do something with the given integers a, b and c"""
        return a + (b*c)

    def Bar2(self, a, b, c):
        """do something else with the given integers a, b and c"""
        print (a*b) + c

import mylib

cheese = mylib.Wine()
qux = Foo()
cheese.setup(qux)
cheese.do_something(1)
cheese.do_something(2)

C ++中的“Wine”对象如下所示:

#include <boost/python.h>
#include <Python.h>

class Wine {

public:  

    Wine() {};

    ~Wine() {};

    void setup(boost::python::object baz) {
         baz_ = baz;
    };

    static void do_something(boost::python::object pyreq) {

        int request = boost::python::extract<int>(pyreq);
        int a = 1;
        int b = 2;
        int c = 3;

        if (request == 1) {
            int d = boost::python::extract<int>(baz_.attr("Bar1")(a, b, c));
        };
        else if (request == 2) {
            baz_.attr("Bar2")(a, b, c);
        };
    };

private:

    static boost::python::object baz_;
};

BOOST_PYTHON_MODULE(mylib)
{
    using namespace boost::python;
    class_<Wine>("Wine")
        .def("do_something", &Wine::do_something)
            .staticmethod("do_something")
        .def("setup", &Wine::setup)
    ;
};

问题在于,在成功执行所有任务后,程序终止于SegFault。这并不是什么大不了的事,因为我需要执行的代码仍然执行,而我需要执行的任务都已执行。 SegFault仅在销毁此C ++“Wine”对象时发生。不过,这是一个不优雅的结果,我想解决这个问题。

我从在线搜索中收集的内容暗示这是对Python的所有权声明不当的问题。最终结果是C ++析构函数被称为两次,第二次调用导致SegFault。

不幸的是到目前为止我还没能解决问题。可用的文档仅涵盖基础知识,我无法复制其他人使用boost智能指针和C ++中的一些花哨的声明/破坏技巧所取得的成功。任何指导都将非常感谢。

1 个答案:

答案 0 :(得分:0)

问题是静态Wine::baz_对象在静态/全局破坏期间被破坏。这是在Python运行时最终确定之后,但由于boost::python::object使用Python C-API,因此它的销毁需要有效的Python运行时(尽管object引用None时可能不行。通过在Python完成之前安排baz_被销毁,你应该能够避免段错误。总体上最干净的方法可能是使baz_成为非静态成员变量。