
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Patrick Horgan Sent: Friday, December 18, 2009 7:00 PM To: boost@lists.boost.org Subject: Re: [boost] [optional] Strict Aliasing Warnings on Trunk
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 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?
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.
After reading this exchange, am I right in adding this to the GCC 'what to do about warnings' guidelines section at https://svn.boost.org/trac/boost/wiki/Guidelines/MaintenanceGuidelines? " warning: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules This warns about undefined behaviour that is likely to cause unwanted results when optimisation is switched on. Recommendation: Fix this by recoding if possible, and document that optimisation may produce wrong results. Include a link to the above example email. Do not suppress the warning with -Wno-strict-warnings - leave that to users after reading the documentation or making their own tests / compile without optimisation.. " Paul --- Paul A. Bristow Prizet Farmhouse Kendal, UK LA8 8AB +44 1539 561830, mobile +44 7714330204 pbristow@hetp.u-net.com