Python 需要关于参考计数的指导吗

Python 需要关于参考计数的指导吗,python,python-extensions,refcounting,Python,Python Extensions,Refcounting,我正在追踪一个内存泄漏,它似乎来自一个长时间运行的进程,该进程包含我编写的一个C扩展。我已经仔细研究了代码和扩展文档,我确信它是正确的,但是我想确定关于PyList和PyDict的引用处理 从文档中我收集到PyDict_SetItem()借用了对key和value的引用,因此我必须在插入后取消引用它们。PyList_SetItem()和PyTuple_SetItem()窃取对插入项的引用,因此我不必取消引用。对吗 创建dict: PyObject *dict = PyDict_New(); if

我正在追踪一个内存泄漏,它似乎来自一个长时间运行的进程,该进程包含我编写的一个C扩展。我已经仔细研究了代码和扩展文档,我确信它是正确的,但是我想确定关于PyList和PyDict的引用处理

从文档中我收集到PyDict_SetItem()借用了对key和value的引用,因此我必须在插入后取消引用它们。PyList_SetItem()和PyTuple_SetItem()窃取对插入项的引用,因此我不必取消引用。对吗

创建dict:

PyObject *dict = PyDict_New();
if (dict) {
    for (i = 0; i < length; ++i) {
        PyObject *key, *value;
        key = parse_string(ctx); /* returns a PyString */
        if (key) {
            value = parse_object(ctx); /* returns some PyObject */
            if (value) {
                PyDict_SetItem(dict, key, value);
                Py_DECREF(value); /* correct? */
            }
            Py_DECREF(key); /* correct? */
        }
        if (!key || !value) {
            Py_DECREF(dict);
            dict = NULL;
            break;
        }
    }
}
return dict;
如果遇到错误,则不会创建任何对象,而是在函数体的前面设置异常:

return PyErr_Format(...);
编辑

下面是valgrind的一些输出——泄漏检查=已满。显然是我的代码泄漏内存,但为什么?为什么PyDict_New位于(递归)链的顶端?这是否意味着当整个内容被垃圾收集时,这里创建的dict不会被删除

这里需要澄清的是:当我用C构建Python类型的嵌套数据结构,然后对最顶层的实例进行DECREF时,Python将递归地对该结构的所有内容进行DECREF,不是吗

==4357==    at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
==4357==    by 0x4F20DBC: PyObject_Malloc (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0x4FC0F98: _PyObject_GC_Malloc (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0x4FC102C: _PyObject_GC_New (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0x4F11EC0: PyDict_New (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0xE5821BA: parse_dict (parser.c:350)
==4357==    by 0xE581987: parse_object (parser.c:675)
==4357==    by 0xE5821F0: parse_dict (parser.c:358)
==4357==    by 0xE581987: parse_object (parser.c:675)
==4357==    by 0xE5823CE: parse (parser.c:727)
在一段看似不相关的代码中,在PyList_追加(列表,项)之后忘记Py_DECREF(项)。PyList_SetItem()会窃取引用,PyList_Append()不会

return PyErr_Format(...);
==4357==    at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
==4357==    by 0x4F20DBC: PyObject_Malloc (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0x4FC0F98: _PyObject_GC_Malloc (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0x4FC102C: _PyObject_GC_New (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0x4F11EC0: PyDict_New (in /usr/lib64/libpython3.6m.so.1.0)
==4357==    by 0xE5821BA: parse_dict (parser.c:350)
==4357==    by 0xE581987: parse_object (parser.c:675)
==4357==    by 0xE5821F0: parse_dict (parser.c:358)
==4357==    by 0xE581987: parse_object (parser.c:675)
==4357==    by 0xE5823CE: parse (parser.c:727)