【问题标题】:SIGSEGV in C extension for PythonPython 的 C 扩展中的 SIGSEGV
【发布时间】:2017-06-28 08:05:41
【问题描述】:

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

该模块内置于 .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);

代码有什么明显错误吗?可能是无效的指针?或者可能是内存问题?

谢谢!

【问题讨论】:

  • this answer on SO 有帮助吗?我认为xd(第一个参数)必须是一个用xdrfile_open打开的文件,natoms(第二个参数)必须由read_xtc_natoms初始化。
  • 感谢您的回复!我已经检查了那个帖子,我传递的 xd 和 natoms 参数是 xdrfile_open 和 read_xtc_natoms 函数的结果

标签: linux python-3.x pointers segmentation-fault python-c-extension


【解决方案1】:

您在xd 中分配内存来保存XDRFILE。然后将xd 移动到dummy,解析一个整数(文件句柄?)并放入xd/dummy。然后你通过释放dummy 来释放xd。然后你调用read_xtc(xd, ...,它将访问释放的内存。如果您的内存分配器决定放弃该页面,您将获得一个 SIGSEGV。

free(dummy) 移动到您实际上不再需要内存的位置。

【讨论】:

  • 感谢您的回复!我试图用 dummy 做的是修复内存泄漏,我实际上并没有将它用于任何事情(或者至少我不是故意的)。如果我打印出变量的地址,我会得到以下信息: malloc 之后的 xd:0000000000572910 dummy:ParseTuple 之后的 0000000000572910 xd:0000000000572790 ParseTuple 之后的 dummy:0000000000572910 我会尝试移动 free(dummy),但我不会问题。
  • xdx = malloc(...的错误路径和if (status...的双臂中泄露。不要只是将xd 的值复制到dummy,然后释放dummy - 你实际上会释放xd。 AFAICS 你需要使用xdrfile_open() 打开文件,这将返回一个XDRFILE,而这绝对不是你可以通过ParseTuple 输入的整数。您可能会发现 this 很有帮助。
  • 我接受这个答案,因为这个链接很有帮助!
猜你喜欢
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
相关资源
最近更新 更多