类型化的 Memoryview 会增加 numpy.array 的引用计数吗?
Does a Typed Memoryview Increase A numpy.array's Reference Count?
下面显示的某些类型的代码导致我在通过 Cython 调用的 C++ 代码中出现内存损坏。我设法解决了它,但想问一下解决它所需的最小值是多少。
假设:
CFoo
是一个 C++ class,其中一些成员 set_ptr
接受一个指向双精度数的指针。 Cython class Foo
持有指向 CFoo
. 的指针
- 在
Foo
的某些 bar
方法中:
- 通过调用
function_returning_a_numpy_array()
. 创建瞬变 numpy.array
、a
- 类型化的内存视图,
a_view
已创建以供查看 a
。
- 使用
CFoo
的成员 set_ptr
将来自 a_view
的指针发送到 CFoo
。
片段:
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
的成员来解决这个问题?我在文档中找不到任何以这种或另一种方式解决的内容。
使 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数组的引用(我不知道为什么)
下面显示的某些类型的代码导致我在通过 Cython 调用的 C++ 代码中出现内存损坏。我设法解决了它,但想问一下解决它所需的最小值是多少。
假设:
CFoo
是一个 C++ class,其中一些成员set_ptr
接受一个指向双精度数的指针。 Cython classFoo
持有指向CFoo
. 的指针
- 在
Foo
的某些bar
方法中:- 通过调用
function_returning_a_numpy_array()
. 创建瞬变 - 类型化的内存视图,
a_view
已创建以供查看a
。 - 使用
CFoo
的成员set_ptr
将来自a_view
的指针发送到CFoo
。
numpy.array
、a
- 通过调用
片段:
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
的成员来解决这个问题?我在文档中找不到任何以这种或另一种方式解决的内容。
使 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数组的引用(我不知道为什么)