Next: Writing extensions in Up: Extending Python with Previous: The mkvalue() function

Reference counts

Here's a useful explanation of INCREF() and DECREF() (after an original by Sjoerd Mullender).

Use XINCREF() or XDECREF() instead of INCREF() or DECREF() when the argument may be NULL - the versions without `X' are faster but wull dump core when they encounter a NULL pointer.

The basic idea is, if you create an extra reference to an object, you must INCREF() it, if you throw away a reference to an object, you must DECREF() it. Functions such as newstringobject(), newsizedstringobject(), newintobject(), etc. create a reference to an object. If you want to throw away the object thus created, you must use DECREF().

If you put an object into a tuple or list using settupleitem() or setlistitem(), the idea is that you usually don't want to keep a reference of your own around, so Python does not INCREF() the elements. It does DECREF() the old value. This means that if you put something into such an object using the functions Python provides for this, you must INCREF() the object if you also want to keep a separate reference to the object around. Also, if you replace an element, you should INCREF() the old element first if you want to keep it. If you didn't INCREF() it before you replaced it, you are not allowed to look at it anymore, since it may have been freed.

Returning an object to Python (i.e. when your C function returns) creates a reference to an object, but it does not change the reference count. When your code does not keep another reference to the object, you should not INCREF() or DECREF() it (assuming it is a newly created object). When you do keep a reference around, you should INCREF() the object. Also, when you return a global object such as None, you should INCREF() it.

If you want to return a tuple, you should consider using mkvalue(). This function creates a new tuple with a reference count of 1 which you can return. If any of the elements you put into the tuple are objects (format codes `O' or `S'), they are INCREF()'ed by mkvalue(). If you don't want to keep references to those elements around, you should DECREF() them after having called mkvalue().

Usually you don't have to worry about arguments. They are INCREF()'ed before your function is called and DECREF()'ed after your function returns. When you keep a reference to an argument, you should INCREF() it and DECREF() when you throw it away. Also, when you return an argument, you should INCREF() it, because returning the argument creates an extra reference to it.

If you use getargs() to parse the arguments, you can get a reference to an object (by using `O' in the format string). This object was not INCREF()'ed, so you should not DECREF() it. If you want to keep the object, you must INCREF() it yourself.

If you create your own type of objects, you should use NEWOBJ() to create the object. This sets the reference count to 1. If you want to throw away the object, you should use DECREF(). When the reference count reaches zero, your type's dealloc() function is called. In it, you should DECREF() all object to which you keep references in your object, but you should not use DECREF() on your object. You should use DEL() instead.



Next: Writing extensions in Up: Extending Python with Previous: The mkvalue() function


guido@cwi.nl