Python C Wrapper内存泄漏

时间:2014-12-18 23:00:29

标签: python c++ c memory-leaks python-module

我在python和C方面经验丰富,但是新编写python模块作为C函数的包装器。对于一个项目,我需要一个名为"得分"运行速度比我在python中运行得快得多,所以我用C语言编写它,并且只是希望能够从python中调用它。它接受一个整数的python列表,我希望C函数获得一个整数数组,该数组的长度,然后返回一个整数回到python。这是我目前的(工作)解决方案。

static PyObject *module_score(PyObject *self, PyObject *args) {
    int i, size, value, *gene;
    PyObject *seq, *data;

    /* Parse the input tuple */
    if (!PyArg_ParseTuple(args, "O", &data))
        return NULL;
    seq = PySequence_Fast(data, "expected a sequence");
    size = PySequence_Size(seq);

    gene = (int*) PyMem_Malloc(size * sizeof(int));
    for (i = 0; i < size; i++)
        gene[i] = PyInt_AsLong(PySequence_Fast_GET_ITEM(seq, i));

    /* Call the external C function*/
    value = score(gene, size);

    PyMem_Free(gene);

    /* Build the output tuple */
    PyObject *ret = Py_BuildValue("i", value);
    return ret;
}

这有效,但似乎泄漏了记忆,而且我无法忽视。我通过暂时使得得分函数返回0并且仍然看到泄漏行为,确保泄漏发生在所示功能中。我原以为对PyMem_Free的调用应该处理PyMem_Malloc的存储,但我目前的猜测是这个函数中的某些东西在每次调用时被分配和保留,因为泄漏行为与调用此函数的次数成正比。功能。我没有正确地执行数组转换的序列,还是我可能无效地返回结束值?任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:3)

seq是一个新的Python对象,因此您需要删除该对象。您应该检查seq是否也为NULL。

像(未经测试)的东西:

static PyObject *module_score(PyObject *self, PyObject *args) {
    int i, size, value, *gene;
    long temp;
    PyObject *seq, *data;

    /* Parse the input tuple */
    if (!PyArg_ParseTuple(args, "O", &data))
        return NULL;
    if (!(seq = PySequence_Fast(data, "expected a sequence")))
        return NULL;

    size = PySequence_Size(seq);

    gene = (int*) PyMem_Malloc(size * sizeof(int));
    for (i = 0; i < size; i++) {
        temp = PyInt_AsLong(PySequence_Fast_GET_ITEM(seq, i));
        if (temp == -1 && PyErr_Occurred()) {
            Py_DECREF(seq);
            PyErr_SetString(PyExc_ValueError, "an integer value is required");
            return NULL;
        }
        /* Do whatever you need to verify temp will fit in an int */
        gene[i] = (int*)temp;
    }

    /* Call the external C function*/
    value = score(gene, size);

    PyMem_Free(gene);
    Py_DECREF(seq):

    /* Build the output tuple */
    PyObject *ret = Py_BuildValue("i", value);
    return ret;
}