我应该对这个块中的任何 PyObject 使用 Py_INCREF 吗?我 Py_DECREFing 我的对象也正确吗?
Should I use Py_INCREF for any of my PyObjects in this block? Also am I Py_DECREFing my objects correctly?
每当我调用此函数时,每次调用都会增加很多内存使用量,因此我认为这里存在一些内存泄漏。
PyObject *pScript, *pModule, *pFunc, *pValue;
PyObject *pArgs = NULL;
long ret = 1;
// Initialize python, set system path and load the module
pScript = SetPyObjectString(PYTHON_SCRIPT_NAME);
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('"PYTHON_SCRIPT_PATH"')");
pModule = PyImport_Import(pScript);
Py_XDECREF(pScript);
if (pModule != NULL) {
// Get function object from python module
pFunc = PyObject_GetAttrString(pModule, operation.c_str());
if (pFunc && PyCallable_Check(pFunc)) {
// Create argument(s) as Python tuples
if (operation == UPDATE_KEY) {
// If operation is Update key, create two arguments - key and value
pArgs = PyTuple_New(2);
}
else {
pArgs = PyTuple_New(1);
}
pValue = SetPyObjectString(key.c_str());
// Set argument(s) with key/value strings
PyTuple_SetItem(pArgs, 0, pValue);
if (operation == UPDATE_KEY) {
// If operation is Update key, set two arguments - key and value
pValue = SetPyObjectString(value.c_str());
PyTuple_SetItem(pArgs, 1, pValue);
}
// Call the function using function object and arguments
pValue = PyObject_CallObject(pFunc, pArgs);
Py_XDECREF(pArgs);
if (pValue != NULL) {
// Parse the return values
ret = PyLong_AsLong(PyList_GetItem(pValue, 0));
value = GetPyObjectString(PyList_GetItem(pValue, 1));
}
else {
ERROR("Function call to %s failed", operation.c_str());
}
Py_XDECREF(pValue);
Py_XDECREF(pFunc);
}
else {
ERROR("Cannot find function in python module");
}
Py_XDECREF(pModule);
}
else {
ERROR("Failed to load python module");
}
当我的代码中的这个 C++ 片段调用 python 脚本时,我泄漏了一些内存,我想知道为什么。我想我的 Py_DECREFs 做错了什么。任何帮助将不胜感激。
我一眼就发现了一个丢失的 decref:
pFunc = PyObject_GetAttrString(pModule, operation.c_str());
if (pFunc && PyCallable_Check(pFunc)) {
// ...
Py_XDECREF(pFunc);
}
这将泄漏任何匹配 operation
.
的不可调用属性
pValue
的两次重新赋值……我认为没关系,因为 PyTuple_SetItem
窃取了对每个原始值的引用。
对于您询问的这一行:
value = GetPyObjectString(PyList_GetItem(pValue, 1));
PyList_GetItem
returns 是借用的引用,所以您不 decref 是正确的。
但是我在任何地方都没有看到 value
或 GetPyObjectString
的声明,所以我不知道那部分在做什么。也许它只是从 PyUnicodeObject *
中获取一个借用的缓冲区并将其复制到某些 C++ wstring
或 UTF-32 字符串类型中,或者它可能正在泄漏 Python 对象或复制的缓冲区,或者返回一个你刚刚泄漏在这里的原始 C 缓冲区,或者......谁知道?
但我当然不相信互联网上的某个人会在快速扫描时找到所有这些。学习使用内存调试器。
或者:您正在使用 C++。 RAII 几乎是使用 C++ 的全部要点 — 换句话说,您可以使用智能指针自动为您减少引用,而不是使用原始 PyObject *
值。或者,更好的是,使用像 PyCXX.
这样的现成库
每当我调用此函数时,每次调用都会增加很多内存使用量,因此我认为这里存在一些内存泄漏。
PyObject *pScript, *pModule, *pFunc, *pValue;
PyObject *pArgs = NULL;
long ret = 1;
// Initialize python, set system path and load the module
pScript = SetPyObjectString(PYTHON_SCRIPT_NAME);
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('"PYTHON_SCRIPT_PATH"')");
pModule = PyImport_Import(pScript);
Py_XDECREF(pScript);
if (pModule != NULL) {
// Get function object from python module
pFunc = PyObject_GetAttrString(pModule, operation.c_str());
if (pFunc && PyCallable_Check(pFunc)) {
// Create argument(s) as Python tuples
if (operation == UPDATE_KEY) {
// If operation is Update key, create two arguments - key and value
pArgs = PyTuple_New(2);
}
else {
pArgs = PyTuple_New(1);
}
pValue = SetPyObjectString(key.c_str());
// Set argument(s) with key/value strings
PyTuple_SetItem(pArgs, 0, pValue);
if (operation == UPDATE_KEY) {
// If operation is Update key, set two arguments - key and value
pValue = SetPyObjectString(value.c_str());
PyTuple_SetItem(pArgs, 1, pValue);
}
// Call the function using function object and arguments
pValue = PyObject_CallObject(pFunc, pArgs);
Py_XDECREF(pArgs);
if (pValue != NULL) {
// Parse the return values
ret = PyLong_AsLong(PyList_GetItem(pValue, 0));
value = GetPyObjectString(PyList_GetItem(pValue, 1));
}
else {
ERROR("Function call to %s failed", operation.c_str());
}
Py_XDECREF(pValue);
Py_XDECREF(pFunc);
}
else {
ERROR("Cannot find function in python module");
}
Py_XDECREF(pModule);
}
else {
ERROR("Failed to load python module");
}
当我的代码中的这个 C++ 片段调用 python 脚本时,我泄漏了一些内存,我想知道为什么。我想我的 Py_DECREFs 做错了什么。任何帮助将不胜感激。
我一眼就发现了一个丢失的 decref:
pFunc = PyObject_GetAttrString(pModule, operation.c_str());
if (pFunc && PyCallable_Check(pFunc)) {
// ...
Py_XDECREF(pFunc);
}
这将泄漏任何匹配 operation
.
pValue
的两次重新赋值……我认为没关系,因为 PyTuple_SetItem
窃取了对每个原始值的引用。
对于您询问的这一行:
value = GetPyObjectString(PyList_GetItem(pValue, 1));
PyList_GetItem
returns 是借用的引用,所以您不 decref 是正确的。
但是我在任何地方都没有看到 value
或 GetPyObjectString
的声明,所以我不知道那部分在做什么。也许它只是从 PyUnicodeObject *
中获取一个借用的缓冲区并将其复制到某些 C++ wstring
或 UTF-32 字符串类型中,或者它可能正在泄漏 Python 对象或复制的缓冲区,或者返回一个你刚刚泄漏在这里的原始 C 缓冲区,或者......谁知道?
但我当然不相信互联网上的某个人会在快速扫描时找到所有这些。学习使用内存调试器。
或者:您正在使用 C++。 RAII 几乎是使用 C++ 的全部要点 — 换句话说,您可以使用智能指针自动为您减少引用,而不是使用原始 PyObject *
值。或者,更好的是,使用像 PyCXX.