On Fri, 19 Jul 2002 07:25:54 PDT, Kyle Jones said:
Sean MacLennan writes:
> I run XEmacs in gdb. After the crash:
>
> (gdb) print var
> $2 = {gu = {type = Lisp_Type_Int_Even, val = 1}, s = {bits = 1, val = 2}, u = {
> bits = 1, val = 2}, ui = 5, i = 5, v = 0x5, cv = 0x5}
Interesting. The gu part of the union apparently has separate
storage space. Could you "print sizeof(var)"?
I'm wondering if this is related to the fact that for most gcc variants, -O2
implies -fstrict-aliasing as well. Sean found that adding an apparently
gratuitous 'sam = var.gu.type' "fixed" the problem - this may be
because
the assignment to 'sam' may be itself gratuitous, but some CSE code then
re-used the assigned value later.
There's an incredible amount of ugly type casting going on in there. I'm not
sure if the compiler is being over-zealous with CSE and/or code migration
because it's been told that strict aliasing is in effect, or if there's really
a subtle casting bug in there. I've appended the gcc doc's description,
maybe somebody more caffienated than I will figure it out. Are we perfectly
clean on the "provided it's accessed through the union tyoe", or are some
of our pointers into the "this code might not" case?
The crash happens when the CPU tries to read the contents of memory
pointed to by a register that just happens to be holding the value 1.
Don't Sparc chipsets get upset at unaligned memory references?
/Valdis
`-fstrict-aliasing'
Allows the compiler to assume the strictest aliasing rules
applicable to the language being compiled. For C (and C++), this
activates optimizations based on the type of expressions. In
particular, an object of one type is assumed never to reside at
the same address as an object of a different type, unless the
types are almost the same. For example, an `unsigned int' can
alias an `int', but not a `void*' or a `double'. A character type
may alias any other type.
Pay special attention to code like this:
union a_union {
int i;
double d;
};
int f() {
a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one
most recently written to (called "type-punning") is common. Even
with `-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type. So, the code above
will work as expected. However, this code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}