我正在阅读教程,以便定义新类型'在python中,https://docs.python.org/2/extending/newtypes.html, 我不明白在这段代码中使用Py_DECREF的目的。
static PyObject *
Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
Noddy *self;
self = (Noddy *)type->tp_alloc(type, 0);
if (self != NULL) {
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
self->last = PyString_FromString("");
if (self->last == NULL)
{
Py_DECREF(self);
return NULL;
}
self->number = 0;
}
return (PyObject *)self;
}
我对引用计数的理解是不完整的,任何帮助都会受到赞赏。
答案 0 :(得分:10)
在这种情况下,Py_DECREF只会释放用tp-> alloc分配的内存。
tp-> alloc将ref count设置为1. Py_DECREF将ref count从1减少到0;因为它发现引用计数为0,它调用适当的函数来释放内存(在这种情况下为Noddy_dealloc。)
如果python C api函数返回NULL,则出现问题;通常设置一个异常(保存在全局变量中)。
如果调用者再次返回NULL,则链接异常,因此'返回NULL'。
答案 1 :(得分:6)
CPython垃圾收集器使用“引用计数”,即它维护一个对象的引用列表。如果对象的引用计数降为零,则表示垃圾收集器为该对象释放空间是安全的。
因此,当我们定义 PyObjects 时,必须明确调用 Py_INCREF 和 Py_DECREF ,这会增加和减少对象的引用计数分别
答案 2 :(得分:0)
引用计数用于管理内存,python跟踪对象的“拥有引用”的数量。当为对象创建新的“拥有参照”时,需要增加参考计数,当拥有参照完成后,需要减少参考计数。如果引用计数降至0,则对象被释放。
C没有任何语言功能可以自动执行此操作,因此必须手动完成。为了减少incref和decref操作的数量,python C API具有“借用”和“窃取”引用的概念。通常,参数会借用引用,而返回值将转移引用的所有权。但是,也有一些例外,例如列表和元组的例程。
tp_alloc使用单个引用创建一个新对象,并将该引用的所有权转让给您。在愉快的路上,您将在完成构建过程后将该引用的所有权转移给您的呼叫者。
但是在不愉快的路径上,您需要删除一个部分构造的对象,因此需要Py_Decref调用。