用于Python的C扩展中的SIGSEGV

用于Python的C扩展中的SIGSEGV

问题描述:

我有一个Python的C扩展模块,它使用函数_xdr_read_xtc读取xtc轨迹。用于Python的C扩展中的SIGSEGV

该模块内置于.so库中,没有问题,大部分时间运行良好。但是,有时我会得到'分段错误(核心转储)'。

static PyObject * _xdr_read_xtc(PyObject *self, PyObject *args) 
{ 
    int natoms; 
    XDRFILE *xd; 
    xd = (XDRFILE *) malloc(sizeof(XDRFILE)); 
    if (xd == NULL){ 
     return NULL;} 

    XDRFILE *dummy; 
    dummy = xd; 

    if (!PyArg_ParseTuple(args, "ii", &xd, &natoms)){ 
     return NULL; 
    } 

    free(dummy); 

    int step = 0; 
    float time; 
    float prec; 
    matrix box; 
    rvec *x; 
    x = malloc(natoms * sizeof(*x)); 
    if (x == NULL){ 
     return NULL;} 

    // read frame 
    int status = read_xtc(xd, natoms, &step, &time, box, x, &prec); 

    if (status == 0 | status == 11){ 
     npy_intp dims[2]= {natoms, 3}; 

     PyArrayObject *matout = (PyArrayObject *) PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, x); 
     PyArray_ENABLEFLAGS(matout, NPY_ARRAY_OWNDATA); 

     PyObject *Frame = Py_BuildValue("Oii", matout, status, step); 
     Py_DECREF(matout); 

     return Frame; 
    } 
    else{ 
     free(x); 
     return NULL; 
    } 
} 

当使用Valgrind进行调试时,我得到'进程以信号11(SIGSEGV)的默认动作终止。访问不在地址0x195688988映射区域内':

int status = read_xtc(xd, natoms, &step, &time, box, x, &prec); 

代码中是否有任何明显错误?一个无效的指针可能?或者它可能是一个记忆问题?

谢谢!

+0

会[此答案在SO](https://*.com/a/42154502/8051589)有帮助吗?我认为'xd'(第一个参数)必须是用'xdrfile_open'打开的文件,'natoms'(第二个参数)必须由'read_xtc_natoms'初始化。 –

+0

感谢您的回复!我已经检查过这个帖子,并且我传递的xd和natoms参数是xdrfile_open和read_xtc_natoms函数的结果 –

您在xd中分配内存以保存XDRFILE。然后,您将xd移动到dummy,解析整数(文件句柄?)并将其放入xd/dummy。然后通过释放dummy免费xd。然后你打电话read_xtc(xd, ...,这将访问free'd内存。如果你的内存分配器决定放开那个页面,你会得到一个SIGSEGV。

free(dummy)移至实际不再需要内存的位置。

+0

感谢您的回复! 我试图做的是假的是修复内存泄漏,我实际上并没有使用它(或者至少我不是故意的)。如果我打印出变量的地址,我得到如下: XD的malloc后:0000000000572910 假:ParseTuple后0000000000572910 XD:ParseTuple后0000000000572790 假:0000000000572910 我会尽量把免费的(虚拟),但我不不认为这是造成问题的原因。 –

+0

'xd'在'x = malloc(...'的错误路径中泄露,并且'if(status ...'的两个部分都被泄露,不要仅仅将'xd'的值复制到'dummy'然后释放'dummy' - 你实际上将释放'xd'。你需要使用'xdrfile_open()'来打开文件,它将返回一个'XDRFILE',这反过来肯定不是一个你可以通过的整数'ParseTuple'。你可能会发现[this](http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/Trajectory/formats/Gromacs/_gromacs/_gromacsmodule.cpp)有帮助。 – user2722968

+0

我接受这个答案,因为链接是非常有帮助的! –