python - 为什么在使用 Python/C API 时会出现此段错误?

标签 python c++ python-2.7 python-c-api

减少 PyObject* 时出现段错误在我使用 Python/C API 的 C++ 代码中,我不知道为什么。我正在使用 C++ 和 Python 2.7。我正在使用新型类来实现 future 的 Python 3 兼容性。

我的目标是创建一个 C++ 类 MyClass作为 Python 模块中定义的类的包装器。在 MyClass构造函数,我传入 Python 模块的名称,导入模块,定位类(它总是有一个预定义的名称 PyClass ),然后调用该类来创建它的实例。然后我存储结果 PyObject*MyClass以备将来使用。在 MyClass析构函数,我删除了存储的 PyObject*以避免内存泄漏。

就定位类和创建它的实例而言,我已经验证了一切工作正常。我什至验证了我可以使用存储的 PyObject*在其他 MyClass方法,例如,访问 PyClass 中的方法.但是,当析构函数执行 decref 时,会导致段错误。

这是我的代码示例。我也调用Py_Initialize()Py_Finalize()在适当的时候在其他地方,为了简洁起见,我省略了一些错误检查代码:
MyPythonModule.py

class PyClass:
    pass
MyClass.h
class MyClass {
public:
    MyClass(const char* modulename);
    ~MyClass();
private:
    void* _StoredPtr;
};
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() 来避免段错误。在析构函数中,但我害怕导致内存泄漏,因为我不明白为什么会发生这种情况。我可以使用_StoredPtr 似乎特别奇怪成功在其他MyClass方法,但我不能decref它。

我也尝试过存储 PyObject* MyClass 中导入的模块并坚持到_StoredPtr之后已减少,但 _StoredPtr decref 仍然是段错误。我尝试注释掉 Py_DECREF(pAttr);行,但这无济于事。

正如我所提到的,我可以在 PyClass 中检索方法。使用 _StoredPtr ,我也尝试将这些存储在 MyClass并在析构函数中取消它们。当我这样做时,我可以 deref _StoredPtr ,但是当我尝试减少方法的 PyObject* 时,它会出现段错误.如果我使用多种方法执行此操作,则始终是导致段错误的最后一个 decref,无论我将它们放入什么顺序。

关于这里发生了什么的任何见解?

最佳答案

这对我有用

#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;}
else{
// do something with _StoredPtr
Py_XDECREF((*PyObject)_StoredPtr)
}
error:
    if (PyErr_Occurred()) {PyErr_Print();}
    Py_XDECREF(pName);
    Py_XDECREF(pModule);
    return;
}

MyClass::~MyClass() {}
我基本上将析构函数之外的 XDECREF 移到了使用 PyObject 的函数中。

关于python - 为什么在使用 Python/C API 时会出现此段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34998007/

相关文章:

android - 当我翻转手机时,Kivy Android APK 崩溃

java - c++ static 关键字对大括号有什么作用?

django - 在AWS的Elastic Search中建立索引时出现连接错误

python - 字典更新序列元素 #0 的长度为 15; 2 是必需的

python - 我的 PySide2 脚本中的语法错误从何而来?

python - 使用 SublimREPL 插件更改用于评估文件的 Python 版本

c++ - LNK2005 和 LNK1169 错误 - C++

c++ - 如何在进程外客户端中获取免注册 COM 对象代理

python - subprocess.check_output逻辑错误

python - 如何在 Django 中查询一天中某个时间之前创建的对象?