Description of problem: The gcc compiler seems to be changing the order of execution of statements such that pointers to memory are being dereferenced before the contents of the memory is initialized when using the -O2 or -O3 options. Version-Release number of selected component (if applicable): gcc version 3.4.6 20060404 (Red Hat 3.4.6-3) How reproducible: Very reproducible Steps to Reproduce: 1. Run the program below first using -O1 and then using -O2 #define N 5 int main() { int in[N]; int out[N]; short *optr=(short *)out; short *iptr=(short *)in; int i,j; printf("Uninitialized in=%x,%x,%x,%x,%x\n\n",in[0],in[1],in[2],in[3],in[4]); for (i=0;i<N;i++) { in[i]=i; *optr++=*iptr++; *optr++=*iptr++; } for (i=0;i<N;i++) printf("in[%d]=%x, out[%d]=%x\n",i,in[i],i,out[i]); return 0; } Actual results: With -O2 you get the following output: Uninitialized in=80483ec,80495ec,bff37748,804828d,0 in[0]=0, out[0]=80483ec in[1]=1, out[1]=80495ec in[2]=2, out[2]=bff37748 in[3]=3, out[3]=804828d in[4]=4, out[4]=0 Note that the output array contains the uninitialized values of the in array. Expected results: Compiled with -O1 you get the expected results where the output array contains the same values as the input array. Uninitialized in=80483f4,80495f4,bfe21068,804828d,0 in[0]=0, out[0]=0 in[1]=1, out[1]=1 in[2]=2, out[2]=2 in[3]=3, out[3]=3 in[4]=4, out[4]=4 Additional info: Obviously, this sample program does not represent the real use case where the problem was first detected. The original code was swapping the low 16-bits with the high 16-bits of a 32-bit integer and was not in doing this in a loop.
The testcase is invalid C, violates the aliasing requirements of the ISO C standard. Search info gcc on -fstrict-aliasing or read directly the ISO C99 standard. -O2 and above turns by default the -fstrict-aliasing option, as a workaround for broken code you can use -fno-strict-aliasing, but better just fix the code to conform to the standard.