Python C API PyObject_Repr分割错误(核心转储)

问题描述:

我想在我的C++项目中使用scikit学习。下面是我使用的代码:Python C API PyObject_Repr分割错误(核心转储)

#include <Python.h> 
    PyObject* loadModule(char* name)// 
    { 
     PyObject* pName = PyString_FromString(name); 
     PyObject* pModule = PyImport_Import(pName); 
     Py_DECREF(pName); 
     return pModule; 
    } 
    void displayPyObject(PyObject* object) 
    { 

    PyObject* objectsRepresentation = PyObject_Repr(object); 
    PyErr_Print(); 
    const char* s = PyString_AsString(objectsRepresentation); 
    PyErr_Print(); 
    std::cout << "[ PYOBJECT ]" << s << std::endl; 

    } 
    //load functions/ attributes from module 
    PyObject* loadComponentFromModule(char* module, char* component) 
    { 
     PyObject* pModule = loadModule(module); 
     PyObject* pyComponent = PyObject_GetAttrString(pModule, component); 
     Py_DECREF(pModule); 
     return pyComponent; 
    } 


    //WRAPPER FOR KMEANS CLUSTERING FROM SCIKIT-LEARN 
class KMeans 
{ 
public: 
    KMeans(int nClusters) 
    { 

     PyObject* KmeansClass = loadComponentFromModule("sklearn.cluster", "KMeans"); 
     PyObject* pName2 = PyInt_FromLong((long) nClusters); 
     PyObject* pArgs = PyTuple_New(1); 
     PyTuple_SetItem(pArgs, 0, pName2); 
     _Kcluster = PyObject_CallObject(KmeansClass, pArgs); 
     _closestor = loadComponentFromModule("sklearn.metrics","pairwise_distances_argmin_min"); 
     Py_DECREF(KmeansClass); 
     Py_DECREF(pName2); 
     Py_DECREF(pArgs); 
    } 
    ~KMeans() 
    { 
     Py_DECREF(_Kcluster); 
     Py_DECREF(_closestor); 
    } 

    void setNumClusters(int nClusters) 
    { 
     std::cout << "change to number cluster: " << nClusters << "\n"; 
     PyObject* nCluster = PyInt_FromLong((long) nClusters); 
     int code = PyObject_SetAttrString(_Kcluster,"n_clusters", nCluster); 
     PyErr_Print(); 
     if (code == -1) 
     { 
      std::cout << "[Error] KMeans.setNumClusters() Failed!! - Number of clusters didn't change!!\n"; 
     } 
     Py_DECREF(nCluster); 
    } 




    void info() 
    { 
     displayPyObject(_Kcluster); 
    } 

private: 
    PyObject* _Kcluster; 
    //PyObject* _result; 
    PyObject* _closestor; 
}; 

PyObject* loadClassifier() 
{ 
    PyObject* loader = loadComponentFromModule("sklearn.externals.joblib", "load"); 
    PyObject* pName2 = PyString_FromString("lda.pkl"); 
    PyObject* pArgs = PyTuple_New(1); 
    PyTuple_SetItem(pArgs, 0, pName2); 
    PyObject* clf = PyObject_CallObject(loader, pArgs); 
    Py_DECREF(loader); 
    Py_DECREF(pName2); 
    Py_DECREF(pArgs); 
// displayPyObject(clf); 
    return clf; 
} 

void produce_error() 
{ 
    std::cout << "============================= LINE 0 =========================================\n"; 
    PyObject* clf = loadClassifier();//"sklearn.externals.joblib", "load"); 
    std::cout << "============================= LINE 1 =========================================\n"; 
    KMeans cluster(8); 
    std::cout << "============================= LINE 2 =========================================\n"; 
    cluster.setNumClusters(5); 
    std::cout << "============================= LINE 3 =========================================\n"; 
    cluster.info(); 
    std::cout << "============================= LINE 4 =========================================\n"; 

} 

int main(int argc, char *argv[]) 
{ 
    Py_Initialize(); 
    produce_error(); 
    Py_Finalize(); 
    return 0; 
} 

我每次运行这个程序,我得到的错误:

============================= LINE 0 ========================================= 
============================= LINE 1 ========================================= 
Segmentation fault (core dumped) 

据我了解,而不调用分类,我不得到任何错误,但每当我调用它(loadClassifier())并创建一个KMeans实例时,就会显示错误。某些时候,错误是在KMeans的构造函数中,我加载模块时,在另一个函数中(这不在这里)使用相同的代码,错误位于PyObject_Repr()内部(在displayPyObject()内部)。

以前任何人都有同样的问题吗?你知道如何解决它吗?提前致谢。

问题已解决。我想到了。因此,如果有人需要,为未来回答这个问题。当你使用Py_DECREF()时,它是合适的。问题来自KMeans构造函数中的这一行:

Py_DECREF(pName2);

因为当你运行Py_DECREF(pArgs);它会尝试释放已被释放的pName2。它会造成不可预知的行为。在评论该行后,万物运行正常。