Cython:在类中使用PyMem_Malloc时出现段错误

时间:2018-07-28 12:58:10

标签: malloc cython bytestring

我很难接受Cython manual中的教科书PyMem_*实现(我在IPython shell中):

In [2]: %%cython -f
   ...: from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
   ...: from libc.string cimport memcpy
   ...: cdef class A:
   ...:     cdef unsigned char **data
   ...:     def __cinit__(self):
   ...:         print('Allocating memory.')
   ...:         self.data = <unsigned char **>PyMem_Malloc(6)
   ...:         if not self.data:
   ...:             raise MemoryError()
   ...:
   ...:     cpdef void assign(self):
   ...:         cdef unsigned char a1[3]
   ...:         cdef unsigned char a2[3]
   ...:         a1 = bytearray(b'123')
   ...:         a2 = bytearray(b'abc')
   ...:         print('Assigning a1.')
   ...:         memcpy(self.data[0], a1, 3)
   ...:         print('Assigning a2.')
   ...:         memcpy(self.data[1], a2, 3)
   ...:         print(self.data[1][: 3])
   ...:
   ...:     def __dealloc__(self):
   ...:         print('Releasing memory.')
   ...:         PyMem_Free(self.data)
   ...: a = A()
   ...: a.assign()
   ...: del(a)
   ...: b = A()
   ...: b.assign()
   ...: del(b)
Allocating memory.
Assigning a1.
Assigning a2.
Segmentation fault (core dumped)

我的代码有什么问题?我从手动示例中看到的唯一区别是我使用的是二维字符数组(它们不是NUL终止的字符串),所以也许我在这里做错了什么?

编辑

段错误发生在随机点。我将实例化和删除行加倍,因为大多数情况下,这是在第二遍执行的。或者即使我连续两次运行相同的Cython单元。

谢谢。

1 个答案:

答案 0 :(得分:1)

根据评论(谢谢!),我重新设计了代码,以使用带有“步幅”的一维数组:

In [8]: %%cython -f
   ...: from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
   ...: from libc.string cimport memcpy
   ...: cdef class A:
   ...:     cdef:
   ...:         unsigned char *data
   ...:         size_t ct, itemsize, size
   ...:     
   ...:     def __cinit__(self, size_t ct, size_t itemsize):
   ...:         print('Allocating memory.')
   ...:         self.data = <unsigned char *>PyMem_Malloc(ct * itemsize)
   ...:         if not self.data:
   ...:             raise MemoryError()
   ...:         self.ct = ct
   ...:         self.itemsize = itemsize
   ...:         self.size = self.ct * self.itemsize
   ...:     
   ...:     cpdef void assign(self):
   ...:         cdef unsigned char a1[3]
   ...:         cdef unsigned char a2[3]
   ...:         a1 = bytearray(b'123')
   ...:         a2 = bytearray(b'abc')
   ...:         print('Assigning a1.')
   ...:         memcpy(self.data, a1, self.itemsize)
   ...:         print('Assigning a2.')
   ...:         memcpy(self.data + self.itemsize, a2, self.itemsize)
   ...:         print(self.data[: self.itemsize])
   ...:         print(self.data[self.itemsize: self.itemsize * 2])
   ...:     
   ...:     def __dealloc__(self):
   ...:         print('Releasing memory.')
   ...:         PyMem_Free(self.data)
   ...: a = A(2, 3)
   ...: a.assign()
   ...: del(a)
Allocating memory.
Assigning a1.
Assigning a2.
b'123'
b'abc'
Releasing memory.

这按预期工作。