试图写入在C扩展中创建的Numpy数组时的SegFault

我在for循环中有一个if子句,我在其中预先定义了state_out:

state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL); 

如果条件是这样的:

  if (conn_ctrdata + i*state_out->strides[0]) = true; } else { *(state_out->data + i*state_out->strides[0]) = false; } 

将这些注释掉时,state_out将返回all-False Numpy数组。 我没看到这个任务有问题。 据我所知,在此代码中调用的结构PyArrayObject中的所有内容都是指针,所以在指针运算之后,它应该指向我打算写的地址。 (如果代码中的条件是通过以这种方式达到值来构建的,并且我知道它有效,因为我设法打印输入数组的值。)然后,如果我想将bool分配给内存中的其中一个部分,我应该通过*(pointer_intended) = true分配它我错过了什么?

编辑:我发现,即使我将一些printf函数放入其中,即使我没有达到这些值:

 if (conn_ctr<sum*2){ printf("True!\n"); } else { printf("False!\n"); } 

我再次获得了SegFault。

非常感谢,其余代码就在这里。

 #include  #include "numpy/arrayobject.h" #include  #include  static PyObject* trace(PyObject *self, PyObject *args); static char doc[] = "This is the C extension for xor_masking routine. It interfaces with Python via C-Api, and calculates the" "next state with C pointer arithmetic"; static PyMethodDef TraceMethods[] = { {"trace", trace, METH_VARARGS, doc}, {NULL, NULL, 0, NULL} }; PyMODINIT_FUNC inittrace(void) { (void) Py_InitModule("trace", TraceMethods); import_array(); } static PyObject* trace(PyObject *self, PyObject *args){ PyObject *adjacency ,*mask, *state; PyArrayObject *adjacency_arr, *mask_arr, *state_arr, *state_out; if (!PyArg_ParseTuple(args,"OOO:trace", &adjacency, &mask, &state)) return NULL; adjacency_arr = (PyArrayObject *) PyArray_ContiguousFromObject(adjacency, NPY_BOOL,2,2); if (adjacency_arr == NULL) return NULL; mask_arr = (PyArrayObject *) PyArray_ContiguousFromObject(mask, NPY_BOOL,2,2); if (mask_arr == NULL) return NULL; state_arr = (PyArrayObject *) PyArray_ContiguousFromObject(state, NPY_BOOL,1,1); if (state_arr == NULL) return NULL; int dims[2], dims_new[1]; dims[0] = adjacency_arr -> dimensions[0]; dims[1] = adjacency_arr -> dimensions[1]; dims_new[0] = adjacency_arr -> dimensions[0]; if (!(dims[0]==dims[1] && mask_arr -> dimensions[0] == dims[0] && mask_arr -> dimensions[1] == dims[0] && state_arr -> dimensions[0] == dims[0])) return NULL; state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL); int i,j; for(i=0;i<dims[0];i++){ int sum = 0; int conn_ctr = 0; for(j=0;jdata + i*adjacency_arr->strides[0] +j*adjacency_arr->strides[1]); if (*(bool *) adj_value == true){ bool mask_value = (mask_arr->data + i*mask_arr->strides[0] +j*mask_arr->strides[1]); bool state_value = (state_arr->data + j*state_arr->strides[0]); if ( (*(bool *) mask_value ^ *(bool *)state_value) == true){ sum++; } conn_ctr++; } } if (conn_ctr<sum*2){ } else { } } Py_DECREF(adjacency_arr); Py_DECREF(mask_arr); Py_DECREF(state_arr); return PyArray_Return(state_out); } 

  if (conn_ctrdata + i*state_out->strides[0]) = true; } else { *(state_out->data + i*state_out->strides[0]) = false; } 

在这里,我天真地做一个指针算术,state_out-> data是一个指向数据开头的指针,它被定义为char的指针: SciPy Doc – Python类型和C结构

 typedef struct PyArrayObject { PyObject_HEAD char *data; int nd; npy_intp *dimensions; npy_intp *strides; ... } PyArrayObject; 

我在这里复制了哪一部分。 state_out-> strides是指向我们所拥有的数组维度长度数组的指针。 在这种情况下,这是一个1d数组。 所以,当我进行指针运算(state_out->data + i*state_out->strides[0])我当然的目的是计算指向数组的第i个值的指针,但是我没有给出指针的类型,所以

我试过了:

 NPY_BOOL *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr; 

变量指向我对for循环感兴趣的值,而state_out_ptr是我写的那个。 我曾经想过,因为我声明这些数组的成分是NPY_BOOL类型,指向数组中数据的指针也是NPY_BOOL类型。 当使用直接操作内存的数据时,这会因SegFault而失败。 这是因为NPY_BOOL是一个整数的enum (如注释中所说的pv。),NumPy在内部使用,。有一个C typedef npy_bool ,以便在代码中使用布尔值。 Scipy Docs 。 当我介绍我的指针类型

 npy_bool *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr; 

分段错误消失了,我成功地操作并返回Numpy数组。

我不是专家,但这解决了我的问题,指出我是不是错了。

源代码中已更改的部分是:

 state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL); npy_bool *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr; npy_intp i,j; for(i=0;idata + i*adjacency_arr->strides[0] +j*adjacency_arr->strides[1]); if (*adj_value_ptr == true){ mask_value_ptr = (mask_arr->data + i*mask_arr->strides[0] +j*mask_arr->strides[1]); state_value_ptr = (state_arr->data + j*state_arr->strides[0]); if ( (*(bool *) mask_value_ptr ^ *(bool *)state_value_ptr) == true){ sum++; } conn_ctr++; } } state_out_ptr = (state_out->data + i*state_out->strides[0]); if (conn_ctr < sum*2){ *state_out_ptr = true; } else { *state_out_ptr = false; } }