Reputation: 1070
I was going through the tutorial for defining 'new types' in python, https://docs.python.org/2/extending/newtypes.html, and I did not understand the purpose of using Py_DECREF in this piece of code.
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;
}
My understanding of reference counting is patchy and any help would be appreciated.
Upvotes: 15
Views: 13161
Reputation: 10514
Reference counting is used to manage memory, python keeps track of the number of "owning references" to an object. When a new "owning reference" is created to an object the reference count needs to be increased, when an owning reference is finished with the reference count needs to be decreased. If the reference count drops to 0 then the object is freed.
C doesn't have any language features to do this automatically, so it must be done manually. To reduce the number of incref and decref operations the python C API has concepts of "borrowing" and "stealing" references. As a general rule parameters borrow references, while return values transfer ownership of a reference. There are a few exceptions though, for example the routines for lists and tuples.
tp_alloc creates a new object with a single reference and transfers ownership that reference to you. On the happy path you in-turn transfer ownership of that reference to your caller after finishing the construction process.
but on the unhappy paths you have a partially constructed object that you need to get rid of, hence the Py_Decref calls.
Upvotes: 1
Reputation: 1070
The CPython Garbage Collector uses 'Reference Counting', i.e it maintains a list of references to an object. If the reference count of an object falls to zero, it then implies that it is safe for the garbage collector to deallocate space for that object.
Hence, when we define PyObjects it is imperative that we explicitly call Py_INCREF and Py_DECREF, which increase and decrease reference counts of an object respectively.
Upvotes: 10
Reputation: 269
In this case, Py_DECREF would simply free the memory allocated with tp->alloc.
tp->alloc sets the ref count to 1. Py_DECREF decreases the ref count from 1 to 0; as it finds the ref count is 0, it calls the appropriate functions to free the memory (Noddy_dealloc in this case.)
If a python C api function returns NULL, something has gone wrong; usually an exception is set (saved in a global variable).
If the caller returns NULL again, the exception is chained, hence the 'return NULL'.
Upvotes: 11