0

I wrote a C wrapper using the Python C API on our development machine (which is 32 bit and runs 32 bit Python 2.7). I have since had to move the wrapper and C source code to another machine which is 64 bit and runs 64 bit Python 2.6. The following code in the C wrapper returns a segmentation fault on the 64 bit machine, but not on the 32 bit machine (it works perfectly there):

static PyObject *tide3_tide_hours(PyObject *self, PyObject *args) {
    double initHour, z0, delt;
    char f_seasonal;
    int numHours;

    // Parse arguments from Python
    if (!PyArg_ParseTuple(args, "ddsid", &initHour, &z0,
                                         &f_seasonal, &numHours, &delt))
        return NULL;

    // Allocate memory for zhr, which is the output we want
    zhr = (double *) malloc ((numHours) *sizeof (double));

    // Call the C source code
    int value = tide_hours(&tc, initHour,
                           z0, f_seasonal, numHours, zhr, delt);

    // Construct the Python return object by defining 
    // a new list and looping over zhr
    int i;
    PyObject *l = PyList_New(0);
    if (!l) {
        printf("No list \n");
        return NULL;
    }

    for (i=0; i < numHours; i++) {
        PyList_Append(l,PyFloat_FromDouble(zhr[i]));
        //printf("%f \n",zhr[i]);
    }

    // Free memory and return the Python list containing zhr to Python
    free (zhr);

    return l;
}

Note that &tc is just a structure class I define in Python and initialize at the beginning of the C wrapper. I want zhr (calculated by tide_hours in the C source code) and can see correct values for it if I uncomment the printf statement in the for loop. If I insert:

printf("Size of zhr: %d\n",sizeof(zhr));

right after allocating memory for zhr, I see '4' on the 32 bit machine and '8' on the 64 bit machine. I'm sure this is the reason why the code is returning a segmentation fault, but I can't figure out how to stop that from happening.

I checked the rest of the C wrapper/Python code and narrowed the problem down to this section. The input arguments are the right value and type. As stated previously, zhr is calculated and output correctly by tide_hours (if I use printf in the for loop), but something is up with the memory allocation that has to do with this 32 to 64 bit switch. I'm unfamiliar with writing C wrappers (this is my first one), so I would like to know if there is a way to fix this or if something else I didn't even think of is causing the problem. Thanks ahead of time and let me know if you need more code.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Ryan Schuster
  • 494
  • 4
  • 15
  • I assume you recompiled, based on the change in size for `zhr`. Have you tried gdb? Start your program running, with a pause for input or sleep. Find the pid, then run `sudo gdb` and in the gdb shell type `attach ` then `continue`. When the segfault happens, gdb will show you where (and probably show a pointer == 0x0 or similar). You are using `zhr` without confirming that the memory was actually allocated, and is likely where the fault is occurring. – kitti Apr 17 '14 at 20:06
  • Where is `zhr` defined at the first place? (And [why do you cast the result of `malloc()`](http://stackoverflow.com/q/605845/296974)?) – glglgl Apr 17 '14 at 20:10
  • @RyanP Yes I recompiled on the new machine. I'll try what you suggested and see what happens. @ glglgl zhr is defined first as double *zhr at the top of the wrapper, outside the function I posted. – Ryan Schuster Apr 17 '14 at 20:14
  • The fact that pointers are 8 bytes on 64-bit systems should not cause a problem, unless you're doing something horribly immoral like assigning it to an `int` and trying to convert it back to a pointer later. – nobody Apr 17 '14 at 20:57

1 Answers1

-1

EDITED:

Two choices:

1) Make sure your wrapper is ported to 64-bit and rebuild it (perhaps this is what you were asking help with -- if so, what is the prototype/implementation for the tide_hours function?), or

2) Use the existing 32-bit compiled wrapper, and then your 64-bit machine would need to have a 32-bit python C runtime installed as well, and then you'd use that one for your wrapper.

For a similar process, read:

Community
  • 1
  • 1
JohnH
  • 2,713
  • 12
  • 21
  • This is really not true. It's certainly easier than fixing the C code, but there's no reason the C code can't be fixed. – nobody Apr 17 '14 at 20:55