减少 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/