2016-03-04 74 views
1

下面显示的一些代码类型导致我在通过Cython调用的C++代码中损坏内存。我已经设法解决它,但想问什么是解决它所需的最小。键入的MemoryView是否增加numpy.array的引用计数?

假设:

  • CFoo是一个C++类的一些部件set_ptr采用指针的两倍。 Cython类Foo包含指向CFoo的指针。
  • Foo一些bar方法:
    • 瞬态numpy.arraya,通过调用function_returning_a_numpy_array()创建。
    • 有类型的内存视图,a_view创建用于查看a。使用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[:](设置为aFoo的成员解决?我无法在文档中找到任何解决这种或那种方法的内容。

回答

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数组的两个引用(我不知道为什么)

+0

这是一个很好的答案 - 谢谢。我有点担心,推断它是像refcount这样的东西是确定性的,因为它是一个可能会改变的实现(因为这个原因,我没有看到Cython生成的C++代码)。尽管如此,这是一个聪明的测试。 –