jeudi 21 mai 2015

Function in C extension randomly stops python program execution

I am relatively new to C extensions for python. I wrote an extension that shows a behavior that seems weird to me. When I run a python script using this extension the script stops randomly after the routine in the extensions has been successfully executed. That is, I have a script like:

import FlowCalc
import numpy as np
np.random.seed(1)

lakeNr = 6
trialNr = 10
a = np.round(np.random.rand(trialNr, lakeNr)).astype(int)
b = np.ones(shape=(lakeNr, lakeNr), dtype=float)

x = FlowCalc.flowCalc(a, b)
print(x)

for i in range(100000):
    print(i)

The script stops sometimes before x is printed, sometimes within the loop at the end, and sometimes it does not stop at all. The probability for the stop depends on the values of lakeNr and trialNr, though I did not find any helpful correlation. It could be that this is just due to the different random numbers with which the input matrix is filled if its dimension is changed. In no case an exception is thrown. The program justs stops as if it was finished.

I was able to detect the function in my extension that must be responsible for this behavior. First I show you my wrapper function:

static PyObject *FlowCalc_flowCalc(PyObject *self, PyObject *args)
{
    PyArrayObject *trials_array, *flows_array, *result;

    /* Parse the input tuple */
    if (!PyArg_ParseTuple(args, "OO", &trials_array, &flows_array)) {
        PyErr_SetString(PyExc_ValueError,
                    "Exception");
        return NULL;
    }
    pymatrix_to_CarrayptrsInt(trials_array);

    return Py_BuildValue("i", 42);

The problem must lay in the function pymatrix_to_CarrayptrsInt:

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

   n=arrayin->dimensions[0];
   m=arrayin->dimensions[1];
   c=ptrvectorInt(n);
   a=(int *) arrayin->data; /* pointer to arrayin data as int */
   for ( i=0; i<n; i++) {
      c[i]=a+i*m; }
   return c;
}

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

This method is a changed reimplementation of pymatrix_to_CarrayptrsDouble:

double **pymatrix_to_CarrayptrsDouble(PyArrayObject *arrayin) {
   double **c, *a;
   int i,n,m;

   n=arrayin->dimensions[0];
   m=arrayin->dimensions[1];
   c=ptrvectorDouble(n);
   a=(double *) arrayin->data; /* pointer to arrayin data as double */
   for ( i=0; i<n; i++) {
      c[i]=a+i*m; }
   return c;
}

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

The version with double works fine and does not cause any problems. I guess that the problem is related to memory management, but I am not sure. Does anyone have an idea what the problem with the int version could be?

A am using python 3.4 64bit with Windows 8 64bit (compiler: Visual Studio 10).

Thanks for your help!




Aucun commentaire:

Enregistrer un commentaire