What is the meaning of Py_INCREF a static PyTypeObject?

Xiang Zhang 18518281186 at 126.com
Thu Nov 12 22:08:27 EST 2015


Thanks for your reply jason. Your reply does give me hints and then I 
read more code and find maybe you are wrong in some points.

I think the meaning of Py_INCREF a static type object is to prevent it 
from being deallocated when it is Py_DECREFed somehow later. Just as you 
said, it may be somehow deallocated when using.

NoddyType is a static struct so I don't think it lives on Python's heap 
and deallocating it is a wrong action. Just as I mentioned, type_dealloc 
seems to only deallocated HEAPTYPE. And by the way, when NoddyType is 
created, it has a reference count 1 with PyVarObject_HEAD_INIT. So if I 
don't Py_INCREF it, when it is somehow Py_DECREDed later, it will reach 
reference count 0 and fail the assert in type_dealloc. If it is 
Py_INCREFed, just like the module holds a reference to it, it will at 
least have a reference count 1 and never reach 0.

On 11/13/2015 02:52 AM, Jason Swails wrote:
>
>
> On Thu, Nov 12, 2015 at 3:05 AM, Xiang Zhang <18518281186 at 126.com 
> <mailto:18518281186 at 126.com>> wrote:
>
>     Recently I am learning Python C API.
>
>     When I read the tutorial
>     <https://docs.python.org/3/extending/newtypes.html#the-basics>,
>     defining new types, I feel confused. After
>     PyType_Ready(&noddy_NoddyType) comes Py_INCREF(&noddy_NoddyType).
>     Actually noddy_NoddyType is a static struct so I don't understand
>     why I need to Py_INCREF it. Since it's Py_INCREFed, does it mean
>     sometimes we also need to Py_DECREF it? But then it seems that
>     type_dealloc will be invoked and it will fail
>     assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
>
>
> ​It is a module attribute, so when the module is imported it has to 
> have a single reference (the reference *in* the module).  If you don't 
> INCREF it, then it will have a refcount of 0, and immediately be ready 
> for garbage collection.  So if you try to use the type from the 
> module, you could get a segfault because it's trying to use an object 
> (type definition) that was already destroyed.
>
> Note that you don't *always* have to INCREF objects after you create 
> them in C.  Some macros and function do that for you. And in some 
> cases, all you want or need is a borrowed reference.  In those cases, 
> Py_INCREF is unnecessary.
>
> The DECREF will be done when it's normally done in Python.  If you do 
> something like
>
> import noddy
> del noddy.NoddyType
>
> ​All that's really doing is removing NoddyType from the noddy 
> namespace and Py_DECREFing it.  Alternatively, doing
>
> import noddy
> noddy.NoddyType = 10 # rebind the name
>
> Then the original object NoddyType was pointing to will be DECREFed 
> and NoddyType will point to an object taking the value of 10.
>
> HTH,
> Jason




More information about the Python-list mailing list