1

I'm trying to build up a python C extension in order to pass a numpy matrix to a C array. I was following the suggestions reported here:

http://wiki.scipy.org/Cookbook/C_Extensions/NumPy_arrays

but when Python tries to run the C line:

v=(float **)malloc((size_t) (n*sizeof(float)));

of the follow portion of code:

float **_ptrvector(long n) { 
    float **v;
    v=(float **)malloc((size_t) (n*sizeof(float)));
    if (!v)   {
        printf("In **ptrvector. Allocation of memory for array failed.");
        exit(0); }
    return v;
}

float **pymatrix_to_carray(PyArrayObject *arrayin)  {
    float **c, *a;
    int i,n,m;

    n = PyArray_DIM(arrayin, 0);
    m = PyArray_DIM(arrayin, 1);
    c=_ptrvector(n);
    a = (float*) PyArray_DATA(arrayin);
    for ( i=0; i<n; i++)  {
        c[i]=a+i*m;  }  
    return c;
}

I get a segmentation fault on my Linux 64 bit machine. The problem is that this code works perfectly on 32 bit machines (both Windows and Linux). Moreover sizeof(size_t) returns correctly 4 on 32bit machines and 8 on 64bit machines. I'm using Python 2.7.1 [EPD 7.0-2 (64-bit)] and GCC 4.1.2 on a Red Hat Linux 4.2.1-44 with kernel version 2.6.18.

I tried also with npy_intp and also Py_ssize_t instead of size_t but no positive effect.

2
  • 1
    if you're not a kernel, libc or compiler hacker, you should use a trailing instead of preceding underscore to mark private symbols Commented Aug 7, 2013 at 13:47
  • Numpy arrays are not guaranteed to be contiguous in memory. Also I think there already is a numpy C-Api function to do this. Commented Aug 7, 2013 at 17:50

1 Answer 1

2

Here you want to allocate memory for pointers to float:

float **v;
v=(float **)malloc((size_t) (n*sizeof(float)));

but you do allocated memory for floats themselfes. On a 32bit system pointers need 4 bytes, so this works.

On a 64bit system pointers need 8 byte, so you might like to change the above line to be:

float ** v = malloc(n * sizeof(float*));

or even more secure to

float ** v = malloc(n * sizeof(*v));

Btw: In C it is not needed to caste the result of malloc/calloc/realloc nor is it recommended. Even more it is dangerous to do so as it might hide awful mistakes.

Sign up to request clarification or add additional context in comments.

6 Comments

Valid point; but OP said the crash occurred at the malloc; you point out that using the space pointed to by v will quickly result in a crash. Any thoughts on that?
@Floris: From my experience malloc() itself only crashes if prior to calling it the memory managment (MM) got corrupted in any way, most propably by writing to unallocated memory and with this destroying/corrupting the MM's internal data structures. Imagine the OP's code in a loop: The first iteration would corrupt the MM, the second iteration's call to malloc() then could easily crash the app.
However, I strongly recommend to fix the issue pointed out by my answer and re-test.
Makes sense - the real problem may have happened elsewhere (for the same reason), or in an earlier pass through this code; the crash occurs when malloc is called again when the heap is corrupted. That makes a ton of sense. Agree it is a serious and fatal flaw in the code.
I checked and now everything is working thanks to the suggestion of alk.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.