[Python-Dev] GC head alignment issue

Tim Peters tim@zope.com
Fri, 12 Oct 2001 18:55:40 -0400


[Paul Svensson]
> ...
> #define gc_next	gc_internals.internal_gc_next
> ...
> Why do you consider this abuse ?

Such macros would be visible to every file #include'ing Python.h, and it's
certainly not our intent to remove 3 ordinary identifiers from the namespace
of every program extending or embedding Python.  That brittleness makes it
"abuse" on its own.

Short of that, it complicates life for developers more than the
straightforward alternate I checked in.  For example, ask a random debugger
for the current value of p->gc_next, and chances are great it will complain
that there is no such member (not doing macro expansion itself); or, on the
flip side, ask for a dump of a PyGC_Head*, and you'll see fields with names
that are utterly surprising because never mentioned in the code using
PyGC_Head pointers.  Telling and using the plain truth doesn't cause any
difficulties, save a tiny bit of extra typing I was happy to do (if I didn't
know better, I'd think *you* had to insert "gc." a hundred times yourself
<wink>).

> This pattern is used all over the place, you can study it for example in
> the system headers for linux of glibc.

Perhaps one reason Python is more stable than, and spends thousands of lines
worming around bugs in, the C libraries it relies on <wink>.

> It's perfectly legitimate to not want to spread knowledge of the innards
> of a struct (it should be wrapped another layer, yes) all over the place.

It's not all over the place -- only the track and untrack macros, and the gc
module, have any business mucking with this union (nee struct); indeed, it's
in the header file only so that the macros can get at the guts.

> ...
> I have anuther issue with the change tho: as written, it forces
> the struct (it's only a union by accident) _gc_head to be aligned,
> but is it obvious that it really has to pad up the size too ?

It may not have to, and that's "a feature".

> If for example sizeof (int) is 4, sizeof (struct *) is 8 and
> sizeof (double) is 16, with 8 byte alignment required for doubles,
> would a compiler be allowed to make sizeof (struct _gc_head[1]) 24,
> while still keeping sizeof (struct _gc_head) at 20 ?

A std-conforming C compiler is not allowed to do that, as, in general, the
compiler can't know whether a struct S* points to the first S in an array of
S, or to an "isolated" S.  So all Ss must have the same layout, regardless
of context.  As Guido said, the C std goes on at length about this stuff.

> This would make a difference when making it part of another struct.

Again, the compiler generally can't know whether a struct S* points to an
instance of S embedded in another struct either, so again it can't change
layout depending on context.

> Try this on for size:
> ----------------------------------------------------------------------
> typedef struct _gc_head {
> 	struct _gc_head *internal_gc_next;
> 	struct _gc_head *internal_gc_prev;
> 	union _gc_head_internals {
> 		int _gc_head_internal_gc_refs;
> 		double dummy;	  /* force worst-case alignment */
> 	}
> } PyGC_Head;
>
> #define gc_refs	_gc_head_internals._gc_head_internal_gc_refs
> -------------------------------------------------------------------------

As before, I've got no use for the macro.  Given that, I'd rather be
consistent in sticking a "gc." prefix on every struct member than on just
one of them.