Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Casting dlsym return value to function pointer

1,297 views
Skip to first unread message

Udo Steinberg

unread,
May 9, 2004, 4: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, 4: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, 2: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, 2: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

0 new messages