
Dean Michael Berris wrote:
I've recently been seeing this error more and more especially on GCC with -Wall:
/home/dean/boost/boost/optional/optional.hpp:407: warning: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules /home/dean/boost/boost/optional/optional.hpp:427: note: initialized from here
and:
/home/dean/boost/boost/function/function_base.hpp:321: warning: dereferencing type-punned pointer will break strict-aliasing rules /home/dean/boost/boost/function/function_base.hpp:325: warning: dereferencing type-punned pointer will break strict-aliasing rules
This is on Linux and GCC 4.4.1.
I'm not an expert in this regard but is there a way to either silence or avoid these warnings? Anything you want me to try from my end?
Thanks in advance and I hope this helps.
It's a fair bit dangerous to silence these since it's the compiler's way of telling you that you're invoking undefined behavior, and that when you turn on optimization your code isn't going to work as expected. The following program generates 6 warnings about breaking strict-aliasing rules, and many would dismiss them. The correct output of the program is: 00000020 00200000 but when optimization is turned on it's: 00000020 00000020 THAT's what the warning is trying to tell you, that the optimizer is going to do things that you don't like. In this case seeing that acopy is set to a and never touched again, strict aliasing lets it optimize by just returning the original value of a at the end. uint32_t swaphalves(uint32_t a) { uint32_t acopy=a; uint16_t *ptr=(uint16_t*)&acopy;// can't use static_cast<>, not legal. // you should be warned by that. uint16_t tmp=ptr[0]; ptr[0]=ptr[1]; ptr[1]=tmp; return acopy; } int main() { uint32_t a; a=32; cout << hex << setfill('0') << setw(8) << a << endl; a=swaphalves(a); cout << setw(8) << a << endl; } Here's the (annotated) x86 assembler generated by gcc 4.4.1 for swaphalves. _Z10swaphalvesj: pushl %ebp movl %esp, %ebp subl $16, %esp movl 8(%ebp), %eax # get a in %eax movl %eax, -8(%ebp) # and store in in acopy leal -8(%ebp), %eax # now get eax pointing at acopy (ptr=&acopy) movl %eax, -12(%ebp) # save that ptr at -12(%ebp) movl -12(%ebp), %eax # get the ptr back in %eax movzwl (%eax), %eax # get 16 bits from ptr[0] in eax movw %ax, -2(%ebp) # store the 16 bits into tmp movl -12(%ebp), %eax # get the ptr back in eax addl $2, %eax # bump up by two to get to ptr[1] movzwl (%eax), %edx # get that 16 bits into %edx movl -12(%ebp), %eax # get ptr into eax movw %dx, (%eax) # store the 16 bits into ptr[1] movl -12(%ebp), %eax # get the ptr again leal 2(%eax), %edx # get the address of ptr[1] into edx movzwl -2(%ebp), %eax # get tmp into eax movw %ax, (%edx) # store into ptr[1] movl -8(%ebp), %eax # return original a. leave ret Scary, isn't it? Of course you could use -fno-strict-aliasing to get the right output, but the generated code won't be as good. A better way to accomplish the same thing without the warning's or the incorrect output is to define swaphalves like this: uint32_t swaphalves(uint32_t a) { union swapem{ uint32_t a; uint16_t b[2]; }; swapem s={a}; uint16_t tmp; tmp=s.b[0]; s.b[0]=s.b[1]; s.b[1]=tmp; return s.a; } This follows the rules and helps the compiler generate MUCH better code: _Z10swaphalvesj: pushl %ebp # save the original value of ebp movl %esp, %ebp # point ebp at the stack frame movl 8(%ebp), %eax # get a in eax popl %ebp # get the original ebp value back roll $16, %eax # swap the two halves of a and return it ret Ignore strict aliasing warnings at your peril. But if you really want to -Wno-strict-warnings will do it. Patrick