More strict aliasing

Till Straumann strauman at slac.stanford.edu
Fri Dec 1 01:16:47 UTC 2006


Here's another example that breaks strict aliasing rules
but illustrates a scenario quite commonly found
in a OS/driver environment:

Assume we have a device (serial device, ethernet chip, fifo, ...)
that can only be accessed with 16-bit bus cycles and we code an
generic 'read' access routine:

typedef uint16_t  PortType;

extern volatile PortType *fifo_port;

static inline void
rd_fifo(void *item, int n_words)
{
PortType *dst = item;
    while (n_words--)
       *dst++ = *fifo_port;
}

Then someone reads bigger items from the device

uint32_t readInt()
{
   uint32_t val;
  
   rd_fifo(&val, sizeof(val)/sizeof(PortType));

   return val;
}

And *bang* they have violated the rule (because val is an uint32_t
and *dst is a uint16_t which must not alias).

Indeed, gcc (checked i386 disassembly) generates code that
doesn't produce the intended result. The store operation of the
second 16-bit word is optimized away.

OK, it would be easy to correct this particular example but
I find the alias rule extremely cumbersome at the OS / driver
level where you often deal with bit-representations etc.

Try to code an inlineable 'rd_fifo()' routine w/o knowledge
about the target objects where the data are to be deposited.

Plus, there are much more obscure cases [dig around in the C99
committee discussions for fun].

Basically, it makes 'serializing' [other than into a byte-stream]
almost impossible. Keep in mind that gcc doesn't fully enforce
the standard [e.g., it doesn't use the rule if the accessed object
is in a different compilation unit].

Another good example are checksums:

inline unsigned csum(void *data, int size);

struct blah xx;

           xx.non_int_nor_char_field = value;

           csum(&xx, sizeof(xx));

If the checksum is computed over 16-bit or 32-bit words
(as usually done in networking stacks)
then there is no guarantee that non_int_nor_char_field
is written before the checksum is computed since the
compiler can assume it doesn't alias to an 'int'.

I wish they had made this optional but *it is not*.
It is the C99 *standard*.

To me, the fact that many software packages 'just work'
doesn't indicate that they obey strictly to the rule but rather
that it is extremely hard to check and enforce. I suspect
that in many cases violation just goes undetected and doesn't
cause problems because the compiler doesn't use the rule for
optimization [because in many cases there is no gain].

-- Till



More information about the users mailing list