我在pyx文件的cython中有以下代码,该代码将wchar_t *转换为python字符串(unicode)
//下面的所有代码都是python 2.7.4
cdef wc_to_pystr(wchar_t *buf):
if buf == NULL:
return None
cdef size_t buflen
buflen = wcslen(buf)
cdef PyObject *p = PyUnicode_FromWideChar(buf, buflen)
return <unicode>p
我在这样的循环中调用了此函数:
cdef wchar_t* buf = <wchar_t*>calloc(100, sizeof(wchar_t))
# ... copy some wide string to buf
for n in range(30000):
u = wc_to_pystr(buf) #<== behaves as if its a memory leak
free(buf)
我在Windows上对此进行了测试,发现内存(在任务管理器中看到)不断增加,因此我怀疑这里可能存在内存泄漏.
这是令人惊讶的,因为:
>根据我的理解,API PyUnicode_FromWideChar()复制了
提供的缓冲区.
>每次为变量“ u”分配一个不同的值,即前一个值
应该释放
>由于源缓冲区(‘buf’)保持原样,并且仅在循环之后才释放
结束时,我原本以为内存在某个特定点之后根本不应该增加
知道我哪里出错了吗?有没有更好的方法来实现Wide Char到python unicode对象?
解决方法:
解决了!!
解:
(注意:该解决方案引用的是我本来不在代码中的一部分代码.发布该解决方案的关键在于我没有任何线索.抱歉,那些想出解决此问题的人…)
在cython pyx文件中,我已经声明了python API,如下所示:
PyObject* PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size)
我在https://github.com/cython/cython/blob/master/Cython/Includes/cpython/init.pxd签出了文档
我已将返回类型声明为PyObject *,因此创建了一个附加引用,但没有明确取消引用.解决方案是更改签名中的返回类型,例如:
object PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size)
根据文档,添加“对象”作为返回类型不会增加任何引用计数,因此在for循环内存中可以正确释放.修改后的“ wc_to_pystr”看起来像这样:
cdef wc_to_pystr(wchar_t *buf):
if buf == NULL:
return None
cdef size_t buflen
buflen = wcslen(buf)
p = PyUnicode_FromWideChar(buf, buflen)
return p