【问题标题】:Python C Extension: Py_DECREF for PyListPython C 扩展:PyList 的 Py_DECREF
【发布时间】:2018-01-27 01:27:34
【问题描述】:

我有一个关于如何在 C 中的 PyList 上正确使用 Py_DECREF() 的问题。假设我有一个名为 build_list() 的函数,它接受一个字符串链表作为其输入参数,如果一切顺利,则返回一个 Python 列表, 或 NULL 如果有错误。

以下是简约示例:

struct strlist {
    char *str;
    size_t len;
    struct strlist *next;
};

PyObject *build_list (struct strlist *inlist) {
    struct strlist *node = NULL;
    PyObject *tmp_obj = NULL;
    int success;

    PyObject *ret_obj = PyList_New(0);
    if (ret_obj == NULL) {
        return NULL;
    }

    node = inlist;
    while (node != NULL) {
        tmp_obj = PyString_FromStringAndSize(node->str, node->len);
        if (tmp_obj == NULL) {
            Py_DECREF(ret_obj);
            return NULL;
        }
        else {
            success = PyList_Append(ret_obj, tmp_obj);
            Py_DECREF(tmp_obj);
            if (success != 0) {
                Py_DECREF(ret_obj);
                return NULL;
            }
        }
        node = node->next;
    }
    return ret_obj;
}

在这种情况下我是否正确使用了Py_DECREF()

我的具体问题是: 如果在发生错误之前已将一些元素附加到列表中,我的代码将直接减少对列表的引用(在success != 0 内),而列表中的元素在技术上仍然具有 refcount 1。我是否应该减少每个元素的在我最终减少对列表的引用之前先引用?

谢谢。

【问题讨论】:

  • 我猜你仍然可以说如果 you 没有 INCREF you 没有 DECREF 但是,对于那些说返回新引用的函数(主要是在创建 python 对象时),您拥有该对象,因此您必须 DECREF。

标签: python c swig


【解决方案1】:

创建list 后,它的引用计数为 1。每个string 的引用计数为 1,并将其附加到列表中会将其增加到 2(因为 list 和您的函数引用它) .所以DECREFAppend() 之后是正确的,因为您的函数不再使用string 本身。 在两个错误路径(tmp_obj == NULLsuccess != 0)内,DECREFlist-object 将释放该对象(因为它的引用计数现在为 0)。 list-object 将遍历它的成员和 DECREF 每个成员,将每个 string 的引用计数减少到 0,释放它们。

长话短说:您的代码是正确的。列表中的元素必须具有(至少)1 的引用计数,因为列表正在引用它们。这是listDECREF 它的成员的专属责任。

作为练习,您可以尝试自己减少字符串的引用计数。解释器很可能会崩溃(可能在exit()),因为当列表被释放时,字符串的引用计数变为-1,触发断言。

【讨论】:

  • 感谢您的详细解释!你能指出我解释 DECREF 对你解释的列表的行为的引用(即走它的成员和 DECREF 他们每个人)?
  • AFAIKS 文档没有指定这一点,这是隐含的行为:Python 中的对象永远不会被拥有,它们总是被引用。每个拥有对其他对象的引用的对象都应该 a) 正确地计算这些引用和 b) 在它们之后正确清理它们。例如,如果一个对象可能持有对其他任意对象的引用,那么它实际上可能引用了它自己。正确参与 c-python 的垃圾收集只是暗示。
  • FWIW 见this
猜你喜欢
  • 1970-01-01
  • 2021-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 2011-02-06
相关资源
最近更新 更多