30

Why should Py_INCREF(Py_None) be required before returning Py_None in C as follows?

Py_INCREF(Py_None);
return Py_None;

If Py_INCREF(Py_None) is omitted, what will happen?

Johnny Lim
  • 5,623
  • 8
  • 38
  • 53

2 Answers2

29

Missing a Py_INCREF will result in an incorrect counting of references for Py_None, which may lead the interpreter to deallocate Py_None. Since Py_None is allocated statically in the Objects/object.c file:

PyObject _Py_NoneStruct = {
  _PyObject_EXTRA_INIT
  1, &PyNone_Type
};

And in Include/object.h there is the define:

#define Py_None (&_Py_NoneStruct)

So what will happen, is that the interpreter will crash with a fatal error:

Fatal Python error: deallocating None

Which is generated by the none_dealloc function in Objects/object.c:

/* ARGUSED */
static void
none_dealloc(PyObject* ignore)
{
    /* This should never get called, but we also don't want to SEGV if
     * we accidentally decref None out of existence.
     */
    Py_FatalError("deallocating None");
}

As stated by that comment, if NoneType didn't have its own deallocating function, you would obtain a Segmentation Fault, since a free call would be done on the stack.

You can test this copying the example in the tutorial, adding a call to Py_DECREF(Py_None) into the Noddy_name function, build the extension and do a loop calling that method.


In the general case a reference count of 0 can cause the program to fail in many different ways.

In particular python is free to re-use the memory used by the objects that were deallocated, which means that suddenly every reference to an object can become references to a random object(or to an empty memory location), and you could see things like:

>>> None   #or whatever object that was deallocated
<ARandomObjectYouNeverSawBefore object at ...>

(This actually happened to me sometimes, when writing C extensions. Some objects where turning into read only buffers at random times due to missing calls to Py_INCREF).

In other situations different kind of errors could be raised, or the interpreter could crash or segfault.

Community
  • 1
  • 1
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • `PyNone` is probably allocated statically (no python source on me to look it up), so we'd try to free statically allocated memory, which would be especially interesting.. in any case nothing good comes from it. – Voo Mar 08 '13 at 08:05
  • @Voo I thought that too, and it turns out it is allocated statically(in `object.c`), and this leads to a fatal error. Anyway my reasoning was correct, except that it holds for the more general case of forgetting to incref a generic object. – Bakuriu Mar 08 '13 at 10:57
26

Py_None is really just another Python object, except without methods.

Python will count the references to any PyObject*. It doesn't matter if it is a string, integer, or None.

If you don't increment the reference count, the Python interpreter will eventually discard the object after its reference count hits 0, thinking that there aren't any pointers to the object. This means that the next time you try to do something with the return value, you will be following a pointer to a location in memory that is not guaranteed to hold Py_None (error, strange value, segmentation fault, etc.).

There are alternatives to having to remember to use Py_INCREF(Py_None):

return Py_BuildValue("");

or

Py_RETURN_NONE;
Jared
  • 25,627
  • 7
  • 56
  • 61
  • 2
    Thanks for the macro. – Mad Physicist Apr 18 '18 at 17:48
  • Will a failure to Py_DECREF a Py_None result in anything wrong, aside from teaching yourself the incorrect mental model that you don't need to worry about Py_None's reference count? – Matthew Moisen Jan 21 '20 at 19:37
  • @MatthewMoisen: If you fail to do it a few billion times on 32 bit Python, it can wrap back to negative values and eventually hit zero coming the other way (and a poorly timed `Py_DECREF` would then try to free it). It would take rather a lot more missed `DECREF`s to hit the problem on 64 bit Python, but it's technically *possible*. – ShadowRanger Oct 15 '21 at 19:01