Python C 扩展:Py_DECREF 用于 PyList
Python C Extension: Py_DECREF for PyList
我有一个关于如何在 C 中的 PyList 上正确使用 Py_DECREF()
的问题。假设我有一个名为 build_list()
的函数,它接受一个字符串链表作为其输入参数,并且 returns 如果一切顺利,则为 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
内),而列表中的元素在技术上仍具有 1 的引用计数。我是否应该递减在我最终递减对列表的引用之前首先引用每个元素?
谢谢。
在创建 list
之后,它的引用计数为 1。每个 string
出生时的引用计数为 1,并将其附加到列表中会将其增加到 2(因为 list
和你的函数引用它)。因此在 Append()
之后 DECREF
是正确的,因为您的函数不再使用 string
本身。
在两个错误路径(tmp_obj == NULL
、success != 0
)中,DECREF
ing list
-object 将释放该对象(因为它的引用计数现在为 0)。 list
-object 将遍历它的成员和 DECREF
每个成员,将每个 string
的引用计数减少到 0,释放它们。
长话短说:您的代码是正确的。列表 中的元素必须 具有(至少)1 的引用计数,因为列表正在引用它们。这是 list
对其成员 DECREF
的专有责任。
作为练习,您可以尝试自己减少字符串的引用计数。解释器很可能会崩溃(可能在 exit()
),因为当释放列表时,字符串的引用计数变为 -1,触发断言。
我有一个关于如何在 C 中的 PyList 上正确使用 Py_DECREF()
的问题。假设我有一个名为 build_list()
的函数,它接受一个字符串链表作为其输入参数,并且 returns 如果一切顺利,则为 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
内),而列表中的元素在技术上仍具有 1 的引用计数。我是否应该递减在我最终递减对列表的引用之前首先引用每个元素?
谢谢。
在创建 list
之后,它的引用计数为 1。每个 string
出生时的引用计数为 1,并将其附加到列表中会将其增加到 2(因为 list
和你的函数引用它)。因此在 Append()
之后 DECREF
是正确的,因为您的函数不再使用 string
本身。
在两个错误路径(tmp_obj == NULL
、success != 0
)中,DECREF
ing list
-object 将释放该对象(因为它的引用计数现在为 0)。 list
-object 将遍历它的成员和 DECREF
每个成员,将每个 string
的引用计数减少到 0,释放它们。
长话短说:您的代码是正确的。列表 中的元素必须 具有(至少)1 的引用计数,因为列表正在引用它们。这是 list
对其成员 DECREF
的专有责任。
作为练习,您可以尝试自己减少字符串的引用计数。解释器很可能会崩溃(可能在 exit()
),因为当释放列表时,字符串的引用计数变为 -1,触发断言。