RFH: aliasing problems

Thomas Doerfler Thomas.Doerfler at embedded-brains.de
Tue Dec 12 08:05:28 UTC 2006


Steven Johnson schrieb:
> Here is concrete help:
> if_ethersubr.c
> Line 598, 692
> sin = (struct sockaddr_in *)&(ifr->ifr_addr);
> change it to
> sin = (struct sockaddr_in *)(void*)&(ifr->ifr_addr);
> Line 881:
> sa = (struct sockaddr *) & ifr->ifr_data;
> to
> sa = (struct sockaddr *)(void*) & ifr->ifr_data;
> Why, because C99 says you can turn any pointer to a void* and any void* 
> to any other pointer.  This will silence the warning.  In this case 
> there is no possibility for common sub expression elimination as there 
> is no manipulation of pointer data between the setting of this value and 
> its use that could trigger the optimisation, and it be working from a 
> previous state, and not a undetected updated state, and so the warning 
> is completely bogus.
> rtems_glue.c
> change:
>         if (rtems_bsdnet_rtrequest (
>                 RTM_ADD,
>                 (struct sockaddr *)&address,
>                 (struct sockaddr *)&gateway,
>                 (struct sockaddr *)&netmask,
>                 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) {
> to:
>         if (rtems_bsdnet_rtrequest (
>                 RTM_ADD,
>                 (struct sockaddr *)(void*)&address,
>                 (struct sockaddr *)(void*)&gateway,
>                 (struct sockaddr *)(void*)&netmask,
>                 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) {

I am not sure about this one: some lines above (line 909) , the code
modifies the content of the source structures, e.g. :

                address.sin_addr.s_addr = INADDR_ANY;
                netmask.sin_addr.s_addr = INADDR_ANY;

Since the cast for the call to rtems_bsdnet_rtrequest "hides" to the
compiler, that in fact a pointer to " struct sockaddr_in" is passed, the
compiler __might__ move the assignment line __behind__ the call to
"rtems_bsdnet_rtrequest". So the effective sequence __might__ be:

rtems_bsdnet_rtrequest (RTM_ADD,
                        (struct sockaddr *)&address,
                        (struct sockaddr *)&gateway,
                        (struct sockaddr *)&netmask,...);
address.sin_addr.s_addr = INADDR_ANY;
netmask.sin_addr.s_addr = INADDR_ANY;

which would be a bit silly :-)

My (provokative) statement is: When the compiler looses track, that
pointers to distinct types ((struct sockaddr*) and (struct
sockaddr_in*)) might point to the same object/memory location, then it
might also can optimize the oder of accesses to these objects (which it
obviously does with really distinct objects, think about the "memory
barrier" discussion some months ago).

Steven, the solution you recommend __might__ work today with GCC 4.1,
but it may break again with gcc-6 or gcc-4.2 or whatever gets smart
enough to shuffle our code araound. As long as we allow GCC to regard
pointers to differrent types to be treated as non-aliased.

> ftpd.c,
> line 657
> if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0)
> change to
> if(bind(s, (struct sockaddr *)(void*)&data_source, sizeof(data_source)) 
>  >= 0)

For this location I see the same problems as stated above.

Hint: <irony> We __might__ overcome this problem, if we would pass every
function call pointers to void instead of typed pointers, because void
pointers seem to possibly alias to everything. </irony>


Embedded Brains GmbH
Thomas Doerfler           Obere Lagerstr. 30
D-82178 Puchheim          Germany
email: Thomas.Doerfler at embedded-brains.de
Phone: +49-89-18908079-2
Fax:   +49-89-18908079-9

More information about the users mailing list