我正在编写代码以将(可能)非常大的整数值存储到由指针引用的chars
数组中。我的代码如下所示:
cdef class Variable:
cdef unsigned int Length
cdef char * Array
def __cinit__(self, var, length):
self.Length = length
self.Array = <char *>malloc(self.Length * sizeof(char)) # Error
for i in range(self.Length):
self.Array[i] = <char>(var >> (8 * i))
def __dealloc__(self):
self.Array = NULL
当我尝试编译代码时,我收到错误,&#34;存储临时Python引用的不安全C衍生物&#34;在评论行。我的问题是:我在C中存储的临时Python参考和存储,以及如何修复它?
答案 0 :(得分:6)
问题在于,在分配给self.Array
之前,正在创建一个临时变量来保存数组,并且一旦该方法退出,它就无效。
请注意documentation建议:
用于在Python堆上分配内存的C-API函数通常比上面的低级C函数更受欢迎,因为它们提供的内存实际上是在Python的内部内存管理系统中考虑的。它们还对较小的内存块进行了特殊优化,通过避免代价高昂的操作系统调用来加速分配。
因此,您可以编写如下,这似乎按预期处理此用例:
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
cdef class Variable:
cdef unsigned int Length
cdef char * Array
def __cinit__(self, var,size_t length):
self.Length = length
self.Array = <char *>PyMem_Malloc(length * sizeof(char))
#as in docs, a good practice
if not self.Array:
raise MemoryError()
for i in range(self.Length):
self.Array[i] = <char>(var >> (8 * i))
def __dealloc__(self):
PyMem_Free(self.Array)
答案 1 :(得分:6)
@ rll的答案在清理代码和“正确执行所有操作”方面做得非常好(最重要的是在问题__dealloc__
中遗漏了内存的重新分配!)。
导致错误的实际问题是您没有cimport
编辑malloc
。因此,Cython假定malloc
是一个Python函数,返回一个要转换为char*
的Python对象。在文件顶部,添加
from libc.stdlib cimport malloc, free
它会起作用。或者使用PyMem_Malloc
(cimporting)作为@rll,这也可以正常工作。