【发布时间】:2015-02-17 20:47:57
【问题描述】:
我在 python 和 C 方面有一定的经验,但对于将 python 模块编写为 C 函数的包装器是新手。对于一个项目,我需要一个名为“score”的函数,它的运行速度比我在 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;
}
这可行,但似乎以我无法忽视的速度泄漏内存。我通过暂时使 score 函数返回 0 并仍然看到泄漏行为来确保在显示的函数中发生泄漏。我曾认为对 PyMem_Free 的调用应该处理 PyMem_Malloc 的存储,但我目前的猜测是,这个函数中的某些东西在每次调用时都会被分配和保留,因为泄漏行为与调用这个函数的次数成正比。我是否没有正确执行序列到数组的转换,或者我是否可能低效地返回结束值?任何帮助表示赞赏。
【问题讨论】:
-
它认为,Python 有一个内存池,调用
PyMem_Free不会立即释放指针。它将在内部释放它,以便 Python 可以重用它而无需再次分配它。但是,我不确定。 -
你在 Linux 上吗?你是如何确定有泄漏的?
-
我在 Windows 上使用 cygwin,这是一个类似 Linux 的环境。我使用 windows 任务管理器和 top 来查看 python 进程消耗越来越多的内存,然后随机等待打印,以查看内存仅在调用此函数而不是其他 python 函数时才增长。
-
我会推荐一个
memory debugging tool,对于Linux,有一个很棒的叫valgrind,你可以在网上搜索任何类似的Windows 工具。您发布的功能,至少在我看来,一点也不错。 -
请注意,您确实有一个问题,即您将内存分配为
sizeof(int)*size,但您使用longs而不是ints 填充它。
标签: python c++ c memory-leaks python-module