Home > front end >  pass a list as an argument from python to C : Segmentation fault (core dumped) when running the sec
pass a list as an argument from python to C : Segmentation fault (core dumped) when running the sec

Time:04-08

I am coding a self-defined python module embedding with C .

test.py

import my_module
column_names = ['ukey', 'OrderRef', 'orderSize']
print(my_module.my_func(column_names))

my_module.cpp (partial)

static PyObject * my_func(PyObject *self, PyObject *args)
{
    Py_Initialize();
    if(!Py_IsInitialized()) { std::cout<<"PythonInit failed!"<<std::endl; }

    PyObject *_list = nullptr;
    int len;
    std::vector<std::string> c_colArray;

    if (!PyArg_ParseTuple(args, "O", &_list)) {
        PyErr_SetString(PyExc_TypeError, "parameter type error.");
        return NULL;
    }
    len = PyList_Size(_list);

    PyObject * _item = nullptr;
    const char * _line;        /* pointer to the line as a string */
    for (int i = 0; i < len; i  ) {
        _item = PyList_GetItem(_list, i); 
        _line = PyUnicode_AsUTF8(_item);
        std::string _elem = _line;
        c_colArray.push_back(_elem);
    }

    Py_DECREF(_list);
    return Py_BuildValue("sss", c_colArray[0].c_str(), c_colArray[1].c_str(), c_colArray[2].c_str());
}

output

('ukey', 'OrderRef', 'orderSize')

The code works fine when first calling my_func, but it crashes when calling it again and arise Segmentation fault (core dumped)

CodePudding user response:

Py_DECREF of the input list in C code is not needed. PyArg_ParseTuple is just do parse only, just like some typecasting, not creating a new Python object.

Py_DECREF(_list);

After that, the column_names in python will become []. Then the my_func is called again, the input list is an empty list in the 2nd call. So c_colArray contains nothing, and the last c_colArray[0] will leading segmentation fault.

The simple solution is to remove the Py_DECREF(_list);

You could easily output the column_names in your python code like this:

import my_module
column_names = ['ukey', 'OrderRef', 'orderSize']
print(my_module.my_func(column_names))
print(column_names)
print(my_module.my_func(column_names))
  • Related