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