something to warry about...

Johannes Stezenbach js at sig21.net
Wed Jan 19 17:20:29 UTC 2011


On Wed, Jan 19, 2011 at 04:17:51PM +0100, Denys Vlasenko wrote:
> On Wed, Jan 19, 2011 at 3:45 PM, Johannes Stezenbach <js at sig21.net> wrote:
> >> But I have a deeper problem here. I do not see it as a good decision
> >> to butcher a readable piece of code into a obfuscated mess *only*
> >> to shut up gcc. gcc has to provide means to do it in some cleaner way.
> >
> > The gcc warning means: This is invalid code, it will break with
> > other compilers (including future gcc versions).  The C99 standard
> > defines the aliasing rules precisely.
> 
> I have no problem with warning per se. I have a problem with near
> impossibility to explain gcc that here I do want mii pointer
> to be treated as "can alias anything".

Well, I think the C99 aliasing rules are designed to allow better optimization.

BTW, if you don't believe the issue is real, try the following experiment
(here with gcc Debian 4.4.5-10 in x86):

struct foo {int i;};
struct bar {int i;};

int f(void)
{
	struct foo foo = { 0 };
	struct bar *bar = (struct bar *)&foo;
	bar->i++;
	return foo.i;
}


$ gcc -Wall -Os -c t.c
t.c: In function ‘f’:
t.c:8: warning: dereferencing pointer ‘bar’ does break strict-aliasing rules
t.c:7: note: initialized from here
$ objdump -dr t.o

t.o:     file format elf32-i386


Disassembly of section .text:

00000000 <f>:
   0:	55                   	push   %ebp
   1:	31 c0                	xor    %eax,%eax
   3:	89 e5                	mov    %esp,%ebp
   5:	83 ec 10             	sub    $0x10,%esp
   8:	c9                   	leave  
   9:	c3                   	ret    


As you can see the function returns 0 not 1.
However, adding some function calls:

struct foo {int i;};
struct bar {int i;};

void g(struct foo *);

int f(void)
{
	struct foo foo = { 0 };
	struct bar *bar = (struct bar *)&foo;

	g(&foo);
	bar->i++;
	g(&foo);
	return foo.i;
}

$ gcc -Wall -Os -c t.c
t.c: In function ‘f’:
t.c:12: warning: dereferencing pointer ‘bar’ does break strict-aliasing rules
t.c:9: note: initialized from here

$ objdump -dr t.o

t.o:     file format elf32-i386


Disassembly of section .text:

0000000 <f>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	53                   	push   %ebx
   4:	83 ec 20             	sub    $0x20,%esp
   7:	8d 5d f4             	lea    -0xc(%ebp),%ebx
   a:	53                   	push   %ebx
   b:	c7 45 f4 00 00 00 00 	movl   $0x0,-0xc(%ebp)
  12:	e8 fc ff ff ff       	call   13 <f+0x13>
			13: R_386_PC32	g
  17:	89 1c 24             	mov    %ebx,(%esp)
  1a:	ff 45 f4             	incl   -0xc(%ebp)
  1d:	e8 fc ff ff ff       	call   1e <f+0x1e>
			1e: R_386_PC32	g
  22:	8b 45 f4             	mov    -0xc(%ebp),%eax
  25:	8b 5d fc             	mov    -0x4(%ebp),%ebx
  28:	c9                   	leave  
  29:	c3                   	ret    

As you can see, foo.i on the stack is incremented before the
second function call.  I'm not smart enough to read from
the C99 standard if this is OK (since function call is a sequence
point), or we were just lucky.  So the particular example
from ifplugd.c might be OK despite the gcc warning, but
in general the "does break strict-aliasing rules" warning
means "it's broken".

If you think fixing the code is too ugly, the obvious
workaround is to use -fno-strict-aliasing.  For the first
function it yields:

00000000 <f>:
   0:	55                   	push   %ebp
   1:	b8 01 00 00 00       	mov    $0x1,%eax
   6:	89 e5                	mov    %esp,%ebp
   8:	83 ec 10             	sub    $0x10,%esp
   b:	c9                   	leave  
   c:	c3                   	ret    


HTH
Johannes


More information about the busybox mailing list