如何创建和使用存储为c++;对象 因此,我想研究一个C++项目,在这里我需要调用一个Python模块,保存它作为一个对象,并多次调用它的一个方法。下面您可以找到包含python对象的类的代码。目前,它是在for循环中实现的,该循环多次调用该方法。实例化该类以及对该类的第一次调用工作正常。但是,在for循环的第一个循环完成后,程序崩溃,并出现“free():invalid size”或有时“double free or corrupt”的错误。我尝试使用valgrind来追踪内存泄漏,但是我得到了很多关于pythonCApi调用的痕迹,我真的不明白 #include <python2.7/Python.h> #include <iostream> #include <algorithm> #include "predictor.hpp" using namespace std; predictor::predictor() { Py_Initialize(); pName = PyString_FromString("predictor"); pModule = PyImport_Import(pName); Py_XDECREF(pName); if (pModule == nullptr) { PyErr_Print(); std::cerr << "Fails to import the module predictor, check installation.\n"; } // dict is a borrowed reference. dict = PyModule_GetDict(pModule); if (dict == nullptr) { PyErr_Print(); std::cerr << "Fails to get the dictionary, check predictor installation.\n"; Py_XDECREF(pModule); } Py_XDECREF(pModule); // Builds the name of a callable class python_class = PyDict_GetItemString(dict, "Predictor"); if (python_class == nullptr || python_class == NULL) { PyErr_Print(); std::cerr << "Fails to get the Python class, check predictor installation.\n"; Py_XDECREF(dict); } Py_XDECREF(dict); // Creates an instance of the class if (PyCallable_Check(python_class)) { object = PyObject_CallObject(python_class, nullptr); if (object == NULL) { cerr << "Fails to create object."; Py_XDECREF(python_class); } Py_XDECREF(python_class); } else { PyErr_Print(); std::cout << "Cannot instantiate the Python class" << std::endl; Py_XDECREF(python_class); } pMethod = PyString_FromString("predict_all"); } predictor::~predictor() { Py_XDECREF(pMethod); Py_XDECREF(object); Py_Finalize(); } long predictor::predict(string rule) { PyObject *pRule = PyString_FromString(rule.c_str()); PyObject *value = PyObject_CallMethodObjArgs(object, pMethod, pRule, NULL); long endValue = PyInt_AsLong(value); if (endValue == -1) { if(!PyErr_Occurred()) { PyErr_Print(); cerr << ""; Py_XDECREF(value); Py_XDECREF(pRule); return NULL; } //PyErr_Print(); } Py_XDECREF(value); Py_XDECREF(pRule); return endValue;} #包括 #包括 #包括 #包括“predictor.hpp” 使用名称空间std; 预测器::预测器() { Py_初始化(); pName=PyString_FromString(“预测器”); pModule=PyImport\u Import(pName); Py_XDECREF(pName); if(pModule==nullptr){ PyErr_Print(); std::cerr

如何创建和使用存储为c++;对象 因此,我想研究一个C++项目,在这里我需要调用一个Python模块,保存它作为一个对象,并多次调用它的一个方法。下面您可以找到包含python对象的类的代码。目前,它是在for循环中实现的,该循环多次调用该方法。实例化该类以及对该类的第一次调用工作正常。但是,在for循环的第一个循环完成后,程序崩溃,并出现“free():invalid size”或有时“double free or corrupt”的错误。我尝试使用valgrind来追踪内存泄漏,但是我得到了很多关于pythonCApi调用的痕迹,我真的不明白 #include <python2.7/Python.h> #include <iostream> #include <algorithm> #include "predictor.hpp" using namespace std; predictor::predictor() { Py_Initialize(); pName = PyString_FromString("predictor"); pModule = PyImport_Import(pName); Py_XDECREF(pName); if (pModule == nullptr) { PyErr_Print(); std::cerr << "Fails to import the module predictor, check installation.\n"; } // dict is a borrowed reference. dict = PyModule_GetDict(pModule); if (dict == nullptr) { PyErr_Print(); std::cerr << "Fails to get the dictionary, check predictor installation.\n"; Py_XDECREF(pModule); } Py_XDECREF(pModule); // Builds the name of a callable class python_class = PyDict_GetItemString(dict, "Predictor"); if (python_class == nullptr || python_class == NULL) { PyErr_Print(); std::cerr << "Fails to get the Python class, check predictor installation.\n"; Py_XDECREF(dict); } Py_XDECREF(dict); // Creates an instance of the class if (PyCallable_Check(python_class)) { object = PyObject_CallObject(python_class, nullptr); if (object == NULL) { cerr << "Fails to create object."; Py_XDECREF(python_class); } Py_XDECREF(python_class); } else { PyErr_Print(); std::cout << "Cannot instantiate the Python class" << std::endl; Py_XDECREF(python_class); } pMethod = PyString_FromString("predict_all"); } predictor::~predictor() { Py_XDECREF(pMethod); Py_XDECREF(object); Py_Finalize(); } long predictor::predict(string rule) { PyObject *pRule = PyString_FromString(rule.c_str()); PyObject *value = PyObject_CallMethodObjArgs(object, pMethod, pRule, NULL); long endValue = PyInt_AsLong(value); if (endValue == -1) { if(!PyErr_Occurred()) { PyErr_Print(); cerr << ""; Py_XDECREF(value); Py_XDECREF(pRule); return NULL; } //PyErr_Print(); } Py_XDECREF(value); Py_XDECREF(pRule); return endValue;} #包括 #包括 #包括 #包括“predictor.hpp” 使用名称空间std; 预测器::预测器() { Py_初始化(); pName=PyString_FromString(“预测器”); pModule=PyImport\u Import(pName); Py_XDECREF(pName); if(pModule==nullptr){ PyErr_Print(); std::cerr,python,c++,python-embedding,Python,C++,Python Embedding,编写Python C/C++代码最关键的部分是正确计算引用。Python区分不同类型的引用,即新的、被盗的和借用的引用 对于您调用的每个API函数,您都必须检查文档以查看它返回的引用类型(如果有) 新引用属于调用者,因此使用Py\u XDECREF通过减少引用计数来释放对象是正确的。确保调用Py\u XDECREF不超过一次,除非在其间增加引用计数。在错误处理中,Py\u XDECREF(pModule)发生两次,例如,因为在错误情况下不返回,所以只需继续 借用的引用归其他人所有,并且引用计数没

编写Python C/C++代码最关键的部分是正确计算引用。Python区分不同类型的引用,即
新的
被盗的
借用的
引用

对于您调用的每个API函数,您都必须检查文档以查看它返回的引用类型(如果有)

新引用属于调用者,因此使用
Py\u XDECREF
通过减少引用计数来释放对象是正确的。确保调用
Py\u XDECREF
不超过一次,除非在其间增加引用计数。在错误处理中,
Py\u XDECREF(pModule)
发生两次,例如,因为在错误情况下不返回,所以只需继续

借用的引用归其他人所有,并且引用计数没有为您增加。因此,只有在您自己增加引用计数之后,调用
Py_XDECREF
才有效

PyModule\u GetDict(pModule)
返回一个借用的引用。您不增加引用计数,但稍后使用
Py\u XDECREF(dict)
将其递减。对于
PyDict\u GetItemString(dict,“predictor”)
,它返回一个借用的引用,而您使用
Py\u XDECREF(python\u类)将其递减


我的假设是,在这两种情况下(
dict
python\u类
),借用的引用都属于使用
PyImport\u导入(pName)导入的模块
pModule
。因此,只要使用
pModule
拥有的借用引用,就很可能不能减少
pModule
引用计数。一旦不再使用那些借用的引用,可以使用
Py\u XDECREF
释放
pModule
。或者,可以增加引用借来的引用计数,但只要你保持
pModule
,这就没有必要了。

好的,所以你的建议解决了第一个内存错误(通过删除借来的代码的所有减量,并删除重复的减量)。然而,之后我得到一个错误,上面写着free()无效的大小。这与我这里的代码或其他什么有关。我重新创建了您的示例。当我删除
dict
python_类的不正确的
PyXDECREF
时,我无法再重现内存问题。valgrind确实报告内存错误。以前,它报告了。我还移动了
pModule
PyXDECREF
在最后一次使用逻辑上属于它的借用引用之后-也就是在实例创建块之后。在这种情况下没有可识别的错误,但基于所有权,这是正确的做法。许多示例似乎将
pModule
引用保留到去初始化,但在引用方面,我看不到错误需要这样做。