[Python-Dev] ANSI strict aliasing and Python

Tim Peters tim.one@comcast.net
Mon, 21 Jul 2003 23:26:31 -0400

> That might be. What they consider wide-spread is the assumption that
> you can access the same memory with different incompatible struct
> types. Atleast the Linux kernel is known to miscompile because of this
> assumption.

When I first googled on this, I found a lot of confused hits.  It appears
that Perl and Parrot need -fno-strict-aliasing for correct operation.

> Whether most of the programs that are incorrect in this respect also
> give an opportunity for the optimizer to generate bad code, I don't
> know. Reportedly, the typical problem is not a bad write order, but a
> failure to reload a value that the compiler "knows" not to be changed.

That makes sense (alas).  We cast PyObject* to and from everything all over
the place, but the only common members are the essentially read-only (after
initialization) pointer to the type object, and the refcount field, which
latter is almost always accessed via macros that cast to PyObject* first.
The other fields can't be accessed at all except via a correctly typed
pointer to the (conceptual) subtype, while the common fields are usually
accessed via a PyObject*.  Since the access paths to a given member don't
normally use both ways, the compiler normally may as well assume the two
kinds of pointers point to non-overlapping stuff.  Perhaps the ob_size
member of var objects is more vulnerable.

> ...
> Yes. Indeed, gcc 3.3 offers a type attribute "may_alias", which causes
> a type to be treated like char* for aliasing purposes.

Sounds like we should add that to PyObject*.  Maybe <wink>.

> I still think that the non-standards-compliance for Python should be
> removed in 2.4. If we ever get a bad optimization because of aliasing
> problems, it will be very time consuming to find the real cause of the
> problem. So the problem is best avoided to begin with.

I'm not fatally opposed to standard code <wink>.  It's unclear whether this
can be done for 2.4, though, or needs to wait for Python 3.  Not *all*
accesses to ob_refcnt and ob_type go thru macros, and if those members get
stuffed behind another access component, some non-core extension modules are
going to stop compiling.  In Zope's C extensions, ob_refcnt is referenced
directly 16 times, and ob_type 174 times.  Many of those are dereferencing
PyObject* vrbls, but many are dereferencing conceptual subtypes (like
BTree*, Sized*, and Wrapper*).  For example,

typedef struct {
  PyObject *obj;
  PyObject *container;
} Wrapper;


  Wrapper *self;

      assert(self->ob_refcnt == 1);

Of course creating work is hard to sell.