在Cython中使用智能指针来处理动态分配的数组

7
我正在编写一个Python包装器,用于调用具有以下签名的函数: double** foo(double** arrayIn, int dim1, int dim2); 我需要在Python包装器中构建arrayIn。一种可能的解决方案在这里给出。然而,由于Cython包括智能指针的支持,我更喜欢实现该解决方案。一种方法是使用malloc和带有自定义删除器的unique_ptr的组合。另一种(更简单)的解决方案是使用libcpp的allocator类
import numpy as np
cimport numpy as np
from libcpp.memory cimport unique_ptr, allocator

def testArray(int dim1, int dim2):
    cdef allocator[double *] ptr_al
    cdef unique_ptr[double *] myptr
    cdef np.ndarray arr
    cdef double[:,:] carr

    myptr.reset(ptr_al.allocate(dim1))
    arr = np.ndarray((dim1,dim2),dtype=np.float64,order='C')
    carr = arr

    myptr.get()[0] = &carr[0,0]
    myptr.get()[1] = &carr[1,0]
    myptr.get()[2] = &carr[2,0]

这段代码可以正确编译和执行(使用Cython 24.1,Python 3.5,VS2015)。我的担忧是是否一切都会被正确地释放/垃圾回收。我理解Python对ndarray负责,而unique_ptr应该负责由allocator创建的double *[]。这是正确的吗?还是代码会造成内存泄漏?有没有办法验证所有内容是否已被正确释放?

应该注意,分配解决方案会破坏大于511个条目的数组堆。我已经为此创建了一个问题 (https://github.com/cython/cython/issues/1592)。我已经能够成功地实现第一个智能指针解决方案,没有任何问题。 - PaxRomana99
回复:错误报告:如果你有选择的话,切换到Py2.7可能会有所帮助(我敢打赌它的支持更成熟)- 我在Linux/GCC/Py2.7/Cy25.2上尝试过这个,并且对于所有类型的dim1都没有问题地运行。 - MWB
我在Linux/GCC4.8.4/Py3.5.2/Cy24.1上进行了测试,也没有出现问题。也许这是一个Windows的问题。 - PaxRomana99
1个回答

2

这段代码会造成内存泄漏吗?

我认为不会泄漏。

有什么办法可以验证所有内容都已正确释放吗?

您可以在循环中调用testArray并查看进程内存是否呈线性增长或保持稳定。由于您知道dim1dim2,如果某些内容未被正确释放,您可以估算出内存泄漏的大小。

在更复杂的情况下,还有其他测试内存泄漏的方法:有C库的调试版本,可以告诉您是否已释放了所有分配的内存。此外,还有像valgrindclangleaksanitizer等工具,但在您的情况下,建议使用循环方法。


我运行了循环100次,创建了一个100 x 100的双精度数组序列,进程内存大致保持不变。看起来这是一个干净的解决方案。 - PaxRomana99

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接