为什么我在使用Python/capi时得到这个segfault?

2024-10-01 07:20:22 发布

您现在位置:Python中文网/ 问答频道 /正文

当我用python/C API对C++代码中的^ {< CD1>}进行解密时,我就得出现一个分割错误,我不知道为什么。我使用C++和Python 2.7。为了将来的python3兼容性,我正在使用新的类。在

< >我的目标是创建一个C++类^ {CD2>},作为Python模块中定义的类的包装器。在MyClass构造函数中,我传入Python模块的名称,导入模块,找到类(它总是有一个预定义的名称PyClass),并调用该类来创建它的一个实例。然后我将得到的PyObject*存储在MyClass中以供将来使用。在MyClass析构函数中,我对存储的PyObject*进行了decref,以避免内存泄漏。在

我已经验证了,只要找到类并创建它的实例,一切都正常工作。我甚至验证了我可以使用其他MyClass中存储的PyObject*来访问{}中的方法。但是,当析构函数执行decref时,它会导致segfault。在

这是我的代码示例。在适当的时候,我还会在其他地方调用Py_Initialize()和{},为了简洁起见,我省略了一些错误检查代码:

MyPythonModule.py

class PyClass:
    pass

MyClass.h

^{pr2}$

MyClass.cpp

#include <Python.h>
#include <iostream>
#include "MyClass.h"

MyClass::MyClass(const char* modulename) {
    _StoredPtr = NULL;

    PyObject *pName = NULL, *pModule = NULL, *pAttr = NULL;

    // Import the Python module.
    pName = PyString_FromString(modulename);
    if (pName == NULL) {goto error;}
    pModule = PyImport_Import(pName);
    if (pModule == NULL) {goto error;}

    // Create a PyClass instance and store a pointer to it.
    pAttr = PyObject_GetAttrString(pModule, "PyClass");
    if (pAttr == NULL) {goto error;}
    _StoredPtr = (void*) PyObject_CallObject(pAttr, NULL);
    Py_DECREF(pAttr);
    if (_StoredPtr == NULL) {goto error;}

error:
    if (PyErr_Occurred()) {PyErr_Print();}
    Py_XDECREF(pName);
    Py_XDECREF(pModule);
    return;
}

MyClass::~MyClass() {
    std::cout << "Starting destructor..."  << std::endl;
    Py_XDECREF((PyObject*)(_StoredPtr));
    std::cout << "Destructor complete."  << std::endl;
}

我知道我可以通过省略析构函数中的Py_XDECREF()来避免segfault,但是我担心会导致内存泄漏,因为我不明白发生这种情况的确切原因。尤其是其他方法似乎不能成功地使用。在

我还尝试过将导入模块的PyObject*存储在MyClass中,并在_StoredPtr递减之后一直保存它,但是_StoredPtr仍然是错误的。我试着把Py_DECREF(pAttr);行注释掉,但没用。在

如前所述,我可以使用_StoredPtr检索PyClass中的方法,我还尝试过将这些方法存储在MyClass中,并在析构函数中对它们进行解密。当我这样做的时候,我可以减少_StoredPtr,但是当我试图减少方法的PyObject*时,它会出错。如果我用几种方法来做这件事,总是最后一个decref导致segfault,不管我把它们放在什么顺序。在

对这里发生的事有什么见解吗?在


Tags: 模块方法函数pyifmyclasserrornull