私は、私が書いた C++ クラスをラップする cython で書かれた python 拡張モジュールに取り組んでいます。
クラッシュ
このpythonモジュールをインポートしてデータを処理する単純なpythonコードがあります。現在、約 4 回に 1 回、モジュールの呼び出し後、終了直前にプログラムが segfault を起こします。これは、すべてのデータが正しく処理されていることも意味します。次のようにセグメンテーション違反します。
/Users/axe/anaconda/bin/python.app: line 2: 73168 Segmentation fault: 11
gdbでデバッグし、実行gdb python
してからrun code.py
、取得します
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 13 at address: 0x0000000000000000
0x00000001000894ae in PyObject_ClearWeakRefs ()
の出力backtrace
は
#0 0x00000001000894ae in PyObject_ClearWeakRefs ()
#1 0x00000001010edae4 in array_dealloc ()
#2 0x000000010007503e in tupledealloc ()
#3 0x00000001000559b7 in insertdict_by_entry ()
#4 0x0000000100059177 in PyDict_SetItem ()
#5 0x000000010005d286 in _PyModule_Clear ()
#6 0x00000001000df8cd in PyImport_Cleanup ()
#7 0x00000001000f0027 in Py_Finalize ()
#8 0x0000000100107e1b in Py_Main ()
#9 0x0000000100000f54 in start ()
したがって、segfault は私の python コードの外で発生します。ipython 内からコードを実行するか、interpter/ipython を Enthought ディストリビューションのものに変更するか、Cython を 1.9.1 から 1.6 にダウングレードすると、問題が解決しないことを述べます。
C++ でのメモリ リーク (?)
これは C++ コードのメモリ リークのように見える可能性があるため (他に考えられる説明があれば教えてください)、C++ クラスの C++ テスト コードで Valgrind を実行しましたが、問題は見つかりませんでした。(私は OSX Mountain Lion を使用しており、Valgrind の最新のトランク バージョンを使用しているにもかかわらず、問題があることが知られているため、問題がないことを 100% 確信しているわけではありません。OSX10.8 抑制ファイルを使用しています。ここで最初に提案されたもの)。とにかく、C++ クラスは new/delete/malloc/free を使用しないので、問題ないはずです。
Cython でのメモリ リーク (?)
クラッシュするpythonコードでvalgrindを実行してみました。上記の OSX 抑制ファイルに加えて、python 抑制ファイルを追加しました。Valgrind は大量の出力を生成してからクラッシュします。出力には、ソース コードへの参照はありません。これは、問題のある cython コードです。
def split_props(np.ndarray[fptype, ndim=1, mode="c"] x,
np.ndarray[fptype, ndim=1, mode="c"] y,
np.ndarray[fptype, ndim=1, mode="c"] ylines):
cdef np.ndarray[fptype, ndim = 1, mode = "c"] areas = np.zeros((ylines.shape[0] + 1), dtype=np.float64, order="c")
cdef np.ndarray[fptype, ndim = 1, mode = "c"] static_moments_x = np.zeros((ylines.shape[0] + 1), dtype=np.float64, order="c")
cdef np.ndarray[fptype, ndim = 1, mode = "c"] inertia_moments_xx = np.zeros((ylines.shape[0] + 1), dtype=np.float64, order="c")
cdef SplitPolygon * SPINSTANCE = new SplitPolygon(100, 100)
SPINSTANCE.split_props(& x[0], # = <fptype *> x.data
& y[0],
x.shape[0],
& ylines[0],
ylines.shape[0],
& areas[0],
& static_moments_x[0],
& inertia_moments_xx[0]
)
del SPINSTANCE
return areas, static_moments_x, inertia_moments_xx
上記の C++ クラスは SplitPolygon です。Python コードでは、cython モジュールからsplit_props
上記の関数のみをインポートするため、メモリ リークはコードのこの部分または C++ コードにあるに違いありません。さらに、Python コードの機能は C++ テスト コードと同じです。
モジュールの別の部分も以下に報告します。これは非常に似ていますが、メモリリークは発生しません
def SplitCirc(np.ndarray[fptype, ndim=1, mode="c"] ycenters,
np.ndarray[fptype, ndim=1, mode="c"] radii,
np.ndarray[fptype, ndim=1, mode="c"] ylines):
cdef np.ndarray[fptype, ndim = 1, mode = "c"] areas = np.zeros((len(ylines) + 1), dtype=np.float64, order="c")
cdef np.ndarray[fptype, ndim = 1, mode = "c"] static_moments_x = np.zeros((len(ylines) + 1), dtype=np.float64, order="c")
cdef np.ndarray[fptype, ndim = 1, mode = "c"] inertia_moments_xx = np.zeros((len(ylines) + 1), dtype=np.float64, order="c")
split_circles(& ycenters[0], & radii[0], len(ycenters),
& ylines[0], len(ylines),
& areas[0], & static_moments_x[0], & inertia_moments_xx[0])
return areas, static_moments_x, inertia_moments_xx
今、私はこの時点で本当に立ち往生しています。cython コードは適切に見えますか? C++ クラスの SplitPolygon に本当にリークがないことを確認するためにコーディングできるテスト ケースはありますか? 他の理由でクラッシュが発生する可能性はありますか?