linuxpython-3.xpointerssegmentation-faultpython-c-extension

SIGSEGV in C extension for Python


I have a C extension module for Python that reads an xtc trajectory using the function _xdr_read_xtc.

The module is built into a .so library without problems and it runs fine most of the time. However, sometimes I get 'Segmentation fault (core dumped)'.

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;
    }
}

When debugging with Valgrind I get 'Process terminating with default action of signal 11 (SIGSEGV). Access not within mapped region at address 0x195688988' in line:

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

Is there anything obviously wrong with the code? An invalid pointer maybe? Or could it be a memory issue?

Thanks!


Solution

  • You allocate memory in xd to hold an XDRFILE. Then you move xd to dummy, parse an integer (file handle ?) and put in into xd/dummy. Then you free xd by freeing dummy. Then you call read_xtc(xd, ... which will access the free'd memory. In case your memory allocator decided to let go of that page, you get a SIGSEGV.

    Move the free(dummy) to where you actually no longer need the memory.