【问题标题】:Does this PyList_Append(list, Py_BuildValue(...)) leak?这 PyList_Append(list, Py_BuildValue(...)) 是否泄漏?
【发布时间】:2010-08-18 13:11:25
【问题描述】:

这会泄漏吗?:

static PyObject* foo(PyObject* self, PyObject* args){
    PyObject* list = PyList_New(0);
    for(int i = 0; i < 100; i++)
        // leak? does PyList_Append increment ref of the temporary?
        PyList_Append(list, Py_BuildValue("i", 42)); 
    return list;
}

不过,无论如何,我认为这样做更好?:

static PyObject* foo(PyObject* self, PyObject* args){
    PyObect* list = PyList_New(100);
    for(int i = 0; i < 100; i++)
        PyList_SetItem(list, i, Py_BuildValue("i", 42));
    return list;
}

【问题讨论】:

    标签: python c


    【解决方案1】:

    PyList_Append 确实增加了引用计数器,所以,是的,第一个示例会泄漏。 PyList_SetItem 没有,这是一个奇怪的例外。

    第二个选项会稍微高效一些,因为列表将被分配到完全正确的大小,而 Python 确实必须在添加项目时动态调整它的大小。

    【讨论】:

    • 感谢您证实我的怀疑!
    • python 文档在哪里发现 PyList_Append 增加了存储对象的引用计数?我在任何地方都没有看到。
    • @MichaelSoulier 我遇到了同样的问题,但在 app1 函数中找到了对 Py_INCREF 的调用,该函数在 PyList_Append 中调用。我在任何文档中都没有看到这个,但在 listobject.c 文件中找到了它
    • 如果我不知道列表的确切大小并且我想追加而不泄漏怎么办?我应该在 PyList_Append(list, my_object) 之后 Py_DecRef(my_object) 吗? PyList_Append 是实例化一个具有相同值的新对象还是使用 my_object 的引用?
    • @MichaelSoulier:默认假设传递给 C 函数的引用是借用的,如果函数需要保存引用,它将适当地增加引用计数。 PyList_Append 遵循此行为,因此其文档无需特别说明。 PyList_SetItem 不遵循这种行为,因此文档特别提到它窃取了对新元素的引用。
    猜你喜欢
    • 2011-01-16
    • 2014-04-12
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 2018-04-28
    • 1970-01-01
    • 2012-01-23
    相关资源
    最近更新 更多