2015-05-21 5 views
0

Я относительно новичок в C-расширениях для python. Я написал расширение, которое показывает поведение, которое кажется мне странным. Когда я запускаю скрипт python с помощью этого расширения, скрипт останавливается случайным образом после, процедура в расширениях была успешно выполнена. То есть, у меня есть сценарий, как:Функция в расширении C случайным образом останавливает выполнение программы 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) 

Сценарий останавливается иногда и до й печатаются, иногда в течение цикла в конце, а иногда он не останавливается на всех. Вероятность остановки зависит от значений 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 может быть?

A am using python 3.4 64bit с Windows 8 64bit (компилятор: Visual Studio 10).

Благодарим за помощь!

+0

Вещь, которая поражает меня как нечетную, - вы не проверяете тип элементов массива. –

+0

@ivan_pozdeev: Пока я знаю, что входные массивы имеют правильный тип. Как только я завершаю модуль расширения, я обязательно добавлю проверку типа. Я в основном скопировал код (версию для double) из http://wiki.scipy.org/Cookbook/C_Extensions/NumPy_arrays. Есть много вещей, которые я буду менять, чтобы подчеркнуть стиль. Однако я не думаю, что эти проблемы связаны с ошибкой. – Samufi

ответ

0

Я понял, как избежать проблемы: функция 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; 
} 

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

 Смежные вопросы

  • Нет связанных вопросов^_^