Функция в расширении C случайным образом останавливает выполнение программы Python

Я относительно новичок в расширениях C для Python. Я написал расширение, которое показывает поведение, которое мне кажется странным. Когда я запускаю скрипт Python с использованием этого расширения, скрипт останавливается случайным образом после успешного выполнения подпрограммы в расширениях. То есть у меня есть скрипт вида:

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)

Сценарий иногда останавливается до того, как x будет напечатан, иногда в конце цикла, а иногда вообще не останавливается. Вероятность стопа зависит от значений lakeNr и trialNr, хотя никакой полезной корреляции я не нашел. Возможно, это просто связано с разными случайными числами, которыми заполняется входная матрица при изменении ее размерности. Ни в коем случае не выдается исключение. Программа просто останавливается, как если бы она была завершена.

Мне удалось обнаружить функцию в моем расширении, которая должна отвечать за такое поведение. Сначала я покажу вам свою функцию-оболочку:

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

Проблема должна заключаться в функции 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;
}

Этот метод представляет собой измененную повторную реализацию 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;
}

Версия с двойным работает нормально и не вызывает никаких проблем. Я предполагаю, что проблема связана с управлением памятью, но я не уверен. Кто-нибудь знает, в чем может быть проблема с версией int?

Я использую python 3.4 64bit с Windows 8 64bit (компилятор: Visual Studio 10).

Спасибо за вашу помощь!


person Samufi    schedule 21.05.2015    source источник
comment
Что мне кажется странным, так это то, что вы не проверяете тип элементов массива.   -  person ivan_pozdeev    schedule 22.05.2015
comment
@ivan_pozdeev: На данный момент я знаю, что входные массивы имеют правильный тип. Как только я доработаю модуль расширения, я обязательно добавлю проверку типов. Я в основном скопировал код (версия для двойного) из wiki.scipy.org/Cookbook/C_Extensions/ NumPy_массивы. Есть еще вещи, которые я изменю, чтобы улучшить стиль. Однако я не думаю, что эти проблемы связаны с ошибкой.   -  person Samufi    schedule 22.05.2015


Ответы (1)


Я придумал, как избежать проблемы: Функция ptrvectorInt, которая должна выделять память для выходного массива, работала некорректно. я заменил его на

int **ptrvectorInt(long dim1) {
   int **v;
   if (!(v = malloc(dim1 * sizeof(int*)))) {
      PyErr_SetString(PyExc_MemoryError,
              "In **ptrvectorInt. Allocation of memory for integer array failed.");
      exit(0); 
   }
   return v;
}

и все работало. Я до сих пор точно не знаю механику ошибки (т.е. почему она появилась и почему случайным образом остановила программу). Однако проблема решается.

person Samufi    schedule 27.05.2015