2017-11-25 206 views
0

我正在使用cython與C++編譯器,並且出現奇怪的分段錯誤等。使用cython與C++訪問結構中的向量的怪異bug

我的問題可以總結與此代碼段:

from libc.stdlib cimport malloc,free 
from libcpp.vector cimport vector 
from libcpp.string cimport string 

cdef struct vstruct: 
    int a 
    double b 
    vector[int] v  
cpdef main(): 
    cdef vstruct* vptr 
    vptr = <vstruct*> malloc(sizeof(vstruct)) 
    vptr[0].v = [1,2] 
    print vptr[0].v 
    print vptr[0].v 

main() 

產生的輸出:

[1,2]
[0,0]

因此,什麼在這裏發生? print語句是否改變了結構體中的向量?我很困惑

回答

2

malloc分配但不初始化內存。因此,當您嘗試指定矢量時,矢量處於未定義狀態,並且表現出不可預測性,導致分段錯誤和不可預知的輸出。 (究竟何時以及如何分割發生故障時也不可預知的 - 在我的情況下,它似乎是在Python的關閉這可能表明,分配到矢量改寫一些Python內部。)

你需要做的就是分配vptr什麼與C++運算符new(它會正確初始化所有組件)。您需要更改

cdef struct vstruct: 

cdef cppclass vstruct: 

(這是爲了安撫用Cython而不是C++ - 有從它們的默認成員訪問的結構和類之間沒有真正的區別在C++中分離)。

你再改

vptr = <vstruct*> malloc(sizeof(vstruct)) 

vptr = new vstruct() 

,同時與他們的默認構造函數初始化所有組件分配內存。

(您還應該在使用del vptr時完全免費)

+0

精彩。 我試圖做到這一點,但Cython抱怨關鍵字new。我不知道cppclass關鍵字。非常感謝你。 那麼,何時以及如何使用malloc來分配堆上的內存?用cython C++中的結構來做這件事是否合理? –

+0

malloc只有對於有一個微不足道的構造函數/析構函數的東西才真正確定。你的結構在沒有vector的情況下會很好,但是因爲vector需要用C++方式管理內存,所以它需要被初始化和銷燬​​。 – DavidW