[Python-Dev] GC head alignment issue (original) (raw)

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


[Paul Svensson]

... #define gcnext gcinternals.internalgcnext ... 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 ).

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 .

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) gchead 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 gchead[1]) 24, while still keeping sizeof (struct gchead) 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 gchead { struct gchead *internalgcnext; struct gchead *internalgcprev; union gcheadinternals { int gcheadinternalgcrefs; double dummy; /* force worst-case alignment */ } } PyGCHead;

#define gcrefs gcheadinternals.gcheadinternalgcrefs -------------------------------------------------------------------------

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.