类型化的Memoryview会增加numpy.array的引用计数吗?

时间:2016-03-04 13:54:56

标签: numpy cython memoryview

下面显示的某些类型的代码导致我通过Cython调用的C ++代码中的内存损坏。我设法解决了这个问题,但想问一下解决它所需的最小是什么。

假设:

  • CFoo是一个C ++类,其中一些成员set_ptr获取指向double的指针。 Cython类Foo包含指向CFoo
  • 的指针
  • bar的某个Foo方法中:
    • 通过调用numpy.array创建暂时afunction_returning_a_numpy_array()
    • 创建了一个类型化的内存视图,a_view用于查看a
    • a_view的指针使用CFoo成员CFoo发送给set_ptr

段:

cdef class Foo:
    cdef CFoo *foo_imp;

    ...

    def bar(self):
        a = function_returning_a_numpy_array()
        cdef double a_view[:] = a
        foo_imp.set_ptr(&a_view[0])

请注意,在此问题的上下文中,对Foo的后续调用将导致CFoo对此指针进行操作。

很明显,由于没有任何内容a,后来对Foo成员的调用可以找到a回收的内存。我通过让a成为Foo的成员来解决这个问题。我的问题是:

  • 通过将double *(设置为&a_view[0])成为Foo的成员来解决这个问题吗?我猜不到。

  • 通过将double a_view[:](设置为a)成为Foo的成员来解决这个问题吗?我无法在文档中找到解决这种或那种方式的任何内容。

1 个答案:

答案 0 :(得分:1)

double*成为Foo的成员不会有帮助(正如您猜测的那样),因为a的引用次数不会增加。

double a_view[:]成员会有所帮助(尽管文档中没有明确说明)。我能看到的最佳提示是http://docs.cython.org/src/userguide/memoryviews.html#memoryview-objects-and-cython-arrays,其中代码示例显示您可以从内存视图的base属性中检索原始对象。

可以使用sys.getrefcount

进一步说明
from __future__ import print_function

import sys
import numpy as np

def f():
    a = np.zeros((5,))
    print(sys.getrefcount(a))
    cdef double[:] b = a
    print(sys.getrefcount(a))

运行它会在第一行打印1,在第二行打印3。所以看起来内存视图实际上存储了两个对numpy数组的引用(我不知道为什么)