av1474@xxxxxxxx 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.