2017-11-25 164 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