[Python-Dev] Re: C new-style classes and GC

Tim Peters tim@zope.com
Fri, 16 May 2003 17:37:07 -0400


[Jim Fulton]
> Hm, I didn't read the PEP, I just went by what Guido told me. :)

That's a good idea -- I think the PEP is out of date here.

> I was told that PyType_Ready fills in tp_alloc and tp_free with
> default values.

And I finally found the code that does that <wink>.

> I updated the noddy example in the docs. In this example, I filled
> in neither tp_alloc or tp_free.  I tested the examples and verified that
> they work.
>
> I just added printf calls to verify that these slots are indeen
> null before the call to PyType_Ready and non-null afterwards.

This is the scoop:  if your type does *not* define the tp_base or tp_bases
slot, then PyType_Ready() sets your type's tp_base slot to
&PyBaseObject_Type by magic (this is the C spelling of the type named
"object" in Python), and the tp_bases slot to (object,) by magic.

A whole pile of type slots are then inherited from whatever tp_bases points
to after that (which is the singleton PyBaseObject_Type if you didn't set
tp_base or tp_bases yourself).

The tp_alloc slot it inherits from object is PyType_GenericAlloc.

The tp_free slot  " " " " is PyObject_Del.

This works, but as we both discovered later, it leads to a segfault if your
type participates in cyclic gc too:  your type *still* inherits a tp_free of
PyObject_Del from object then, but that's the wrong deallocation function
for gc'able objects.  However, the default tp_alloc is aware of gc, and does
the right thing either way.

Guido, would you be agreeable to making this magic even more magical?  It
seems to me that we can know whether the current type intends to participate
in cyclic gc, and give it a correct default tp_free value instead if so.
The hairier type_new() function already has this extra level of
Py_TPFLAGS_HAVE_GC-dependent magic for dynamically created types, setting
tp_free to PyObject_Del in one case and to PyObject_GC_Del in the other.
PyType_Ready() can supply a wrong deallocation function by default
("explicit is better than implicit" has no force when talking about
PyType_Ready() <wink>).