因此,我试图编写一个C函数,它接受numpy数组对象,提取数据,进行一些操作,并将另一个c数组作为numpy数组对象返回。所有东西都是无缝工作的,我使用python包装器,这有助于在python端进行轻松的操作。然而,我正面临着一个记忆泄漏。我有一个双输出指针,它是malloc编辑的,在返回到调用Python函数之前,我将其包装到python数组对象中,
PyObject *arr;
int nd = 2;
npy_intp dims[] = {5, 10};
double *data = some_function_that_returns_a_double_star(x, y, z);
arr = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, (void *)data);
return arr;
然而,这会造成内存泄漏,因为数据从未被释放,而且我做了一些googling搜索,发现这是此类应用程序中的一个问题,解决方案并不简单。我在上面找到的最有用的资源是给在这里。我无法实现此页面从给定示例中谈到的析构函数。有人能帮我吗?更具体地说,我在寻找类似的东西,
PyObject *arr;
int nd = 2;
npy_intp dims[] = {5, 10};
double *data = some_function_that_returns_a_double_star(x, y, z);
arr = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, (void *)data);
some_destructor_that_plug_memLeak_due_to_data_star(args);
return arr;
发布于 2018-10-10 03:14:03
在您不了解的链接中描述的技术是一个很好的方法:创建一个Python对象,它知道如何在销毁时释放内存,并使其成为返回数组的基础。
听起来您可能已经被创建新扩展类型的复杂性所淹没了。幸运的是,这没必要。Python附带了一种类型,用于在销毁时执行任意C级清理:胶囊,它将指针和析构函数捆绑在一起,并在胶囊被销毁时调用析构函数。
要为您的内存创建一个容器,首先,我们定义一个析构函数:
void capsule_cleanup(PyObject *capsule) {
void *memory = PyCapsule_GetPointer(capsule, NULL);
// I'm going to assume your memory needs to be freed with free().
// If it needs different cleanup, perform whatever that cleanup is
// instead of calling free().
free(memory);
}
然后设置一个胶囊作为数组的基础
PyObject *capsule = PyCapsule_New(data, NULL, capsule_cleanup);
PyArray_SetBaseObject((PyArrayObject *) arr, capsule);
// Do not Py_DECREF the capsule; PyArray_SetBaseObject stole your
// reference.
这将确保您的内存一旦不再使用就会被释放。
发布于 2019-09-18 21:43:32
虽然PyCapsule
方法更一般地起作用,但当数组通过设置OWNDATA
标志收集垃圾时,您可以获得numpy来释放数组中的内存。
double *data = some_function_that_returns_a_double_star(x, y, z);
PyObject *arr = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, (void *)data);
PyArray_ENABLEFLAGS((PyArrayObject*) arr, NPY_ARRAY_OWNDATA);
https://stackoverflow.com/questions/52731884
复制相似问题