将宽字符串转换为python字符串时可能发生内存泄漏

时间:2014-12-07 17:05:09

标签: python python-2.7 unicode cython

我在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上对此进行了测试,观察结果是内存(如任务管理器中所示)不断增加,因此我怀疑此处可能存在内存泄漏。

这是令人惊讶的,因为:

  1. 根据我的理解,API PyUnicode_FromWideChar()会复制 提供缓冲区。
  2. 每次变量&#39; u&#39;被赋予不同的值,即前一个值 应该被释放
  3. 由于源缓冲区(&#39; buf&#39;)保持原样并且仅在循环之后释放 结束,我期待记忆不应该在某一点之后增加
  4. 知道我哪里错了吗?有没有更好的方法将Py Char实现为python unicode对象?

1 个答案:

答案 0 :(得分:3)


<强>解决!! 解决方案:

(注意:解决方案是指我原本不在问题中的一段代码。我在发帖时没有任何线索说它会抓住解决这个问题的关键。对于那些想过要解决的人来说很抱歉。 ..)

在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 *,因此创建了一个额外的ref,我没有明确地解释。解决方案是更改签名中的返回类型,如:

object PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size)

根据文档添加'object'作为返回类型不会增加任何引用计数,因此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