Casting dlsym return value to function pointer

1108 views
Skip to first unread message

Udo Steinberg

unread,
May 9, 2004, 10:18:24 PM5/9/04
to
The following program is a shortened example for dlsym() usage from an
older manpage (error checking and such omitted):

#include <dlfcn.h>
#include <stdio.h>

int main (void) {

double (*cosine)(double);
void *handle;

handle = dlopen ("libm.so", RTLD_LAZY);
cosine = dlsym (handle, "cos");
dlclose (handle);

return 0;
}

Compiling it with gcc-3.4 the compiler complains about a bad cast:

gcc -W -Wall -pedantic -fstrict-aliasing foo.c -ldl
foo.c: In function `main':
foo.c:11: warning: ISO C forbids assignment between function pointer
and `void *'

Making the cast explicit, i.e. changing line 11 as follows:
cosine = (double (*)(double)) dlsym (handle, "cos");

yields the following compiler warning:

foo.c: In function `main':
foo.c:11: warning: ISO C forbids conversion of object pointer to
function pointer type

Newer manpages for dlsym suggest to cast the return value of dlsym as
follows:
*(void **) (&cosine) = dlsym (handle, "cos");

Now the compiler complains:
foo.c: In function `main':
foo.c:11: warning: dereferencing type-punned pointer will break
strict-aliasing rules


So my question is - how am I supposed to cast the return value of
dlsym, so that gcc-3.4 doesn't yield any warnings, when using the
following compiler flags: -W -Wall -pedantic -fstrict-aliasing

-Udo.

Bjorn Reese

unread,
May 9, 2004, 10:50:39 PM5/9/04
to
On Sun, 09 May 2004 13:18:24 -0700, Udo Steinberg wrote:

> So my question is - how am I supposed to cast the return value of
> dlsym, so that gcc-3.4 doesn't yield any warnings, when using the
> following compiler flags: -W -Wall -pedantic -fstrict-aliasing

Looks like your caught between two standards (ISO C and SUSv3).
For further information see the RATIONALE section for dlsym in
SUSv3:

http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html

--
mail1dotstofanetdotdk

Michael Kerrisk

unread,
May 10, 2004, 8:41:58 AM5/10/04
to


Yes. The current suggested remedy is somethng like the following:

int (*funcp)(int); /* Ptr to function with 1 int arg. */
*(void **) (&funcp) = dlsym(handle, symbol);

gcc -pedantic warns that "ANSI C forbids the use of cast expressions
as lvalues" for the seemingly equivalent:

(void *) funcp = dlsym(handle, symbol);

This problem is avoided by the first technique because we are
assigning to an address pointed to by the assignment's lvalue.

Cheers,

Michael

Erik Max Francis

unread,
May 10, 2004, 8:50:55 AM5/10/04
to
Michael Kerrisk wrote:

> Yes. The current suggested remedy is somethng like the following:
>
> int (*funcp)(int); /* Ptr to function with 1 int arg. */
> *(void **) (&funcp) = dlsym(handle, symbol);
>
> gcc -pedantic warns that "ANSI C forbids the use of cast expressions
> as lvalues" for the seemingly equivalent:
>
> (void *) funcp = dlsym(handle, symbol);
>
> This problem is avoided by the first technique because we are
> assigning to an address pointed to by the assignment's lvalue.

No, you meant:

funcp = (int (*)(int)) dlsym(...);

The cast on the left-hand side is functionally useless and actually
creates a second problem (the result of a cast is not an lvalue).

(Note that in C++ you can't use a reinterpret_cast, since that's
explicitly forbidden for conversion between function pointers and data
pointers; you must use the old-style C cast.)

--
__ Erik Max Francis && m...@alcyone.com && http://www.alcyone.com/max/
/ \ San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
\__/ I would have liked to have seen Montana.
-- Capt. Vasily Borodin

Reply all
Reply to author
Forward
0 new messages