1

以下に示すタイプのコードによって、Cython を介して呼び出された C++ コードでメモリ破損が発生しました。なんとか解決できましたが、解決するために最低限必要なものは何ですか?

仮定する:

  • CFooset_ptr一部のメンバーが double へのポインターを取るC++ クラスです。Cython クラスFooは へのポインタを保持しますCFoo
  • barのいくつかのメソッド内でFoo:
    • 一時的なnumpy.arrayaは、 を呼び出すことによって作成されfunction_returning_a_numpy_array()ます。
    • 表示用に型指定されたメモリa_viewビューが作成されaます。
    • からのポインターがusingのメンバーa_viewに送信されます。CFooCFooset_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で reclaimed のメモリを見つけることができることは明らかですaaのメンバーにすることでこれを解決しましたFoo。私の質問は次のとおりです。

  • double *これは(に設定&a_view[0]) を のメンバーにすることで解決されFooますか? いいえと思います。

  • double a_view[:]これは(に設定a) を のメンバーにすることで解決されFooますか? これに何らかの方法で対処しているドキュメントには何も見つかりません。

4

1 に答える 1

1

double*のメンバーを作成しても、 Foo(ご想像のとおり) の参照カウントがインクリメントされないため、役に立ちaません。

メンバーを作成するdouble a_view[:]と役立ちます(ただし、ドキュメントからは明確ではありません)。私が見ることができる最良のヒントはhttp://docs.cython.org/src/userguide/memoryviews.html#memoryview-objects-and-cython-arraysbaseです。コード例は、属性から元のオブジェクトを取得できることを示していますメモリービュー。

を使用して、さらに説明を加えることができます。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 が出力され、2 番目の行に 3 が出力されます。そのため、メモリ ビューは実際には numpy 配列への 2 つの参照を格納しているようです (理由はわかりません)。

于 2016-03-04T17:22:59.763 に答える