Why does this code break strict-aliasing rules?
Andrew Haley
aph@redhat.com
Fri Nov 13 10:21:00 GMT 2009
Jonathan Lennox wrote:
> John S. Fine wrote:
>
>> Jonathan Lennox wrote:
>>> Am I missing something, or is gcc mis-compiling correct code?
>>>
>> gcc is correct.
>>
>> You put a value into union derived_union* u and then read a value out
>> of ((struct base*)u)
>>
>> That is a violation of strict aliasing.
>>
>> Annoying as it is, the compiler is free to assume the value you put in
>> is unrelated to the value you read, so the value you put in u is never
>> used, so the optimizer can remove that operation.
>
> But I didn't put a value into derived_union* u -- every time I
> initialize, read, or write the structure, I'm accessing it via a 'struct
> base' or 'struct base *'. The function call just casts to a
> derived_union*, and then casts back.
>
> I was under the impression it was valid to cast between a pointer to a
> structure element and a pointer to the containing structure, so long as
> the underlying memory really is the containing structure -- this is how
> you can implement something equivalent to casting between C++ base and
> derived classes, e.g. Was I wrong?
That's not what you're doing here. Of course, you can cast a structure
pointer to the type of its first element, and back. But here you are
casting a pointer to a type that the object to which it points does not
have:
struct derived2
{
struct base base;
double c;
};
union derived_union
{
struct derived1 d1;
struct derived2 d2;
};
...
struct derived2 d2 = { {5, 5}, 5.0 };
int d2_a;
set_base_a_field((union derived_union*)&d2, 0);
Here, the underlying memory really is *not* of type derived_union.
> Is there any convenient way to get this code to work reliably, without
> either restructuring my objects or having to use the big hammer of
> -fno-strict-aliasing?
Do not lie to the compiler, or it will bite you.
Andrew.
More information about the Gcc-help
mailing list