【问题标题】:Function in C extension randomly stops python program executionC扩展中的函数随机停止python程序执行
【发布时间】:2015-05-21 23:59:57
【问题描述】:

我对 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)

脚本有时会在打印 x 之前停止,有时会在最后的循环内停止,有时它根本不会停止。停止的概率取决于lakeNrtrialNr 的值,尽管我没有发现任何有用的相关性。这可能只是由于输入矩阵的维度发生变化时填充的随机数不同。 在任何情况下都不会引发异常。程序就像结束一样停止。

我能够在我的扩展程序中检测到必须对这种行为负责的函数。首先我向你展示我的包装函数:

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

感谢您的帮助!

【问题讨论】:

  • 让我感到奇怪的是你没有检查数组元素的类型。
  • @ivan_pozdeev:现在我知道输入数组确实有正确的类型。一旦我完成了扩展模块,我肯定会添加一个类型检查。我基本上从wiki.scipy.org/Cookbook/C_Extensions/NumPy_arrays 复制了代码(double 版本)。为了改进风格,我会改变更多的东西。但是,我认为这些问题与错误无关。

标签: python c memory-management random python-c-extension


【解决方案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;
}

一切正常。我仍然不完全了解错误的机制(即它出现的原因以及它随机停止程序的原因)。不过,问题解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-18
    • 2012-01-09
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2012-07-16
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多