We have a library that packs a float into a character array, then unpacks it later. The values of the float were coming out wrong when compiled with -O2. If a value of 999.9 is packed in, a value of 0 comes out. This code worked on all previous versions of g++, and works on g++3.2 for linux, redhat 8.0. The command line used is: g++ -O2 prog.C -o prog -Wall No warnings are reported. The output is fval 999.9 fval 0 The output should be fval 999.9 fval 999.9 Release: Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/3.2/specs Environment: SunOS 5.8 Generic_108528-12 sun4u sparc SUNW,Sun-Fire-280R How-To-Repeat: #include <iostream> using namespace std; static char *buf; static char *bufPtr; void pack( float fval ) { // Following are volatile to prevent optimizers from reusing the // allocated stack space for other purposes following the last // direct reference to the address of the float value. (The g++ 3.2 // optimizer apparently gets faked out by the cast of the float address // to an int address, and thinks the float address is free for reuse // prior to the underlying bits actually being packed into the buffer) // volatile float fvalTmp = fval; // volatile int *ival = (volatile int *)&fvalTmp; int *ival = (int *)&fval; *bufPtr++ = (*ival >> 24) & 0xff; *bufPtr++ = (*ival >> 16) & 0xff; *bufPtr++ = (*ival >> 8) & 0xff; *bufPtr++ = *ival & 0xff; } void unpack( float& val ) { int ival ; ival = *bufPtr++ << 24 ; ival |= (*bufPtr++ << 16) & 0x00ff0000; ival |= (*bufPtr++ << 8) & 0x0000ff00; ival |= (*bufPtr++ & 0xff); val = *((float *)&ival); } int main(int argc, char **argv ) { buf = new char[4]; bufPtr = buf; float fval( 999.9 ); cerr << "fval " << fval << endl; pack( fval ); bufPtr = buf; unpack( fval ); cerr << "fval " << fval << endl; } Unformatted: Configured with: ../configure --with-as=/usr/ccs/bin/as --with-ld=/usr/ccs/bin/ld --disable-nls Thread model: posix gcc version 3.2
Fix: To fix the problem, uncomment the two volatile declarations in the pack function, and comment out the next int declaration.
State-Changed-From-To: open->closed State-Changed-Why: Not a bug. Your code breaks the ISO C++ aliasing rules. GCC automatically turns on -fstrict-aliasing (see the docs, Optimize options section) at -O2, so you must either fix your code or compile it with -fno-strict-aliasing.