This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Strict aliasing and pointers to functions


av1474@comtv.ru writes:

 > I was recently bitten by a piece of code that gcc (3.3.3 and 3.4.1)
 > compiled without warnings and which ran just fine, but only on i386,
 > on ppc it failed. However on ppc with 3.4.6 the code failed. Reduced
 > test case is presented bellow.
 > 
 > <safp.c>
 > #include <stdlib.h>
 > #include <string.h>
 > #include <stdio.h>
 > #include <dlfcn.h>
 > 
 > struct {
 >          void (*fummy) (void);
 >          void (*dummy) (void);
 >          void (*tummy) (void);
 > } funcs;
 > 
 > void dummy (void)
 > {
 > }
 > 
 > int main (void)
 > {
 >          printf ("dummy is %p\n", __extension__ (void *) &dummy);
 >          *(void **) (char **) (void *) &funcs.dummy = dlsym (NULL, "dummy");

Wow.

OK, this is the rule: don't take the address of an lvalue and cast it
to a pointer of a different type.  Doing do via (char **) (void *)
doesn't help -- all it can do is silence a useful warning.

 >          if (!funcs.dummy) {
 >              printf ("failed %p\n", *(void **) (char **) (void *) &funcs.dummy);
 >          }
 >          else {
 >              printf ("success %p\n", __extension__ (void *) funcs.dummy);
 >          }
 >          exit (EXIT_SUCCESS);
 > }
 > </safp.c>
 > 
 > Addmitedly this is somewhat dodgy, but gcc does not complain even
 > with `-Wall', `-W|-Wextra' and `-pedantic'.

You have aked the compiler to warn you about non-ISO operations, and
you then want to perform non-ISO operations without warnings!  Make
your mind up!

-pedantic means to complain about non-ISO operations.  But ISO doesn't
allow object pointer to function pointer conversions, and that's what
you're doing.  So why do you want to use pedantic?  The *only* point
of pedantic is to be sure you're writing portable ISO code.  But here
you're deliberately writing non-ISO code.  It doesn't make sense.

 > <transcript-ppc>
 > safp$ uname -m
 > ppc
 > safp$ gcc --version | head -1
 > gcc (GCC) 3.4.6
 > safp$ gcc -O2 -Wall -W -pedantic safp.c -o safp -ldl -g -Wl,-E
 > safp$ ./safp
 > dummy is 0x10001778
 > failed 0x10001778
 > </transcript-ppc>
 > 
 > <transcript-i386>
 > safp$ uname -m
 > i686
 > safp$ gcc --version|head -1
 > gcc (GCC) 3.3.3 (SuSE Linux)
 > safp$ gcc -O2 -Wall -Werror -W -pedantic  -o safp ./safp.c -ldl -Wl,-E
 > safp$ ./safp
 > dummy is 0x8048700
 > success 0x8048700
 > safp$ gcc-4.1.0 --version|head -1
 > gcc-4.1.0 (GCC) 4.1.0
 > safp$ gcc-4.1.0 -O2 -Wall -Werror -Wextra -W -pedantic  -o safp ./safp.c -ldl -Wl,-E
 > safp$ ./safp
 > dummy is 0x80486f0
 > success 0x80486f0
 > </transcript-i386>
 > 
 > If the code is indeed in error w.r.t. to standard aliasing rules then
 > perhaps someone could explain how to fill those pointers to functions
 > in some other manner and without resorting to removing -W... flags from
 > GCCs command line. Thanks in advance.

union
{
  void *barf;
  void (*fptr) (void);
} bilge;

  bilge.barf = dlsym (NULL, "dummy");
  funcs.dummy = bilge.fptr;

 > P.S. It seems like i can use the tripple casting trick once again
 >         instead of straightforward `struct.field', but this again begs
 >         the question of portability/conformance.

Why are you using the "triple casting trick"?  All it can possibly do
is silence a warning; it won't make the code correct.

Andrew.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]