clumsy cast in dlopen.3
The dlopen.3 man page contains this text:
*(void **) &cosine = dlsym(handle, "cos");
This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u;
u.pointer = dlsym(handle, "cos");
...
printf("%f\n", u.cosine(2.0));Bruno
Alejandro Colomar
maintainerHi Bruno,
Quoted 8 lines · Bruno Haible
The dlopen.3 man page contains this text:
*(void **) &cosine =
dlsym(handle, "cos");This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
I think I agree. Dereferencing the pointer &cosine with a type different than the type of the object is not allowed. I've CCed Martin, who might be able to confirm.
Quoted 8 lines
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u; u.pointer = dlsym(handle, "cos"); ... printf("%f\n", u.cosine(2.0));
This is seems much better, indeed.
Have a lovely day!
Alex
Quoted 6 lines
Bruno
Signature · 1 line
<https://www.alejandro-colomar.es>
Hello,
I agree the cast is not nice, (someone for a extension of C standard ?) but i have to admit that i have never seen the trick with the union. But it needs some explaination. The comment in the example is already huge, i would ask for a comment subsektion for this behavier here.
btw: the original code in the example looks like this ... cosine = (typeof(double (double)) *) dlsym(handle, "cos");
my2c
wh
________________________________________
Von: Alejandro Colomar <[email protected]>
Gesendet: Donnerstag, 14. Mai 2026 13:29:20
An: Bruno Haible
Cc: [email protected]; Martin Uecker
Betreff: Re: clumsy cast in dlopen.3
Hi Bruno,
Quoted 8 lines · Bruno Haible
The dlopen.3 man page contains this text:
*(void **) &cosine =
dlsym(handle, "cos");This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
I think I agree. Dereferencing the pointer &cosine with a type different than the type of the object is not allowed. I've CCed Martin, who might be able to confirm.
Quoted 8 lines
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u; u.pointer = dlsym(handle, "cos"); ... printf("%f\n", u.cosine(2.0));
This is seems much better, indeed.
Have a lovely day!
Alex
Quoted 6 lines
Bruno
Alejandro Colomar
maintainerHi Walter,
Quoted 5 lines · Walter Harms
Hello,
I agree the cast is not nice, (someone for a extension of C standard ?) but i have to admit that i have never seen the trick with the union. But it needs some explaination. The comment in the example is already huge, i would ask for a comment subsektion for this behavier here.
The thing about unions is that the only two ways for type punning that are blessed by ISO C are unions and memcpy(3). Everything else isn't allowed.
Perfectly valid:
static_assert(sizeof(int) == sizeof(float));
union u {int i; float f;};
float f;
union u u;
u.i = 42;
f = u.f;Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; memcpy(&f, &i, sizeof(float));
UB:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; f = *(float *) &i;
Have a lovely day!
Alex
Quoted 53 lines
btw: the original code in the example looks like this ... cosine = (typeof(double (double)) *)
dlsym(handle, "cos");my2c
wh________________________________________
Von: Alejandro Colomar <[email protected]>
Gesendet: Donnerstag, 14. Mai 2026 13:29:20
An: Bruno Haible
Cc: [email protected]; Martin Uecker
Betreff: Re: clumsy cast in dlopen.3Hi Bruno,
Quoted 8 lines · Bruno Haible
The dlopen.3 man page contains this text:
*(void **) &cosine =
dlsym(handle, "cos");This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
I think I agree. Dereferencing the pointer &cosine with a type different than the type of the object is not allowed. I've CCed Martin, who might be able to confirm.
Quoted 8 lines
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u; u.pointer = dlsym(handle, "cos"); ... printf("%f\n", u.cosine(2.0));This is seems much better, indeed.
Have a lovely day!
AlexQuoted 6 lines
Bruno
Signature · 1 line
<https://www.alejandro-colomar.es>
There is no such thing needed here, you just do
double (*cosine)(double);
cosine = dlsym(handle, "cos");
Best,
Martin
Am Freitag, dem 15.05.2026 um 11:56 +0200 schrieb Alejandro Colomar:
Quoted 102 lines
Hi Walter,
Quoted 5 lines · Walter Harms
Hello,
I agree the cast is not nice, (someone for a extension of C standard ?) but i have to admit that i have never seen the trick with the union. But it needs some explaination. The comment in the example is already huge, i would ask for a comment subsektion for this behavier here.The thing about unions is that the only two ways for type punning that are blessed by ISO C are unions and memcpy(3). Everything else isn't allowed.
Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); union u {int i; float f;}; float f; union u u; u.i = 42; f = u.f;Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; memcpy(&f, &i, sizeof(float));UB:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; f = *(float *) &i;Have a lovely day!
AlexQuoted 53 lines
btw: the original code in the example looks like this ... cosine = (typeof(double (double)) *)
dlsym(handle, "cos");my2c
wh________________________________________
Von: Alejandro Colomar <[email protected]>
Gesendet: Donnerstag, 14. Mai 2026 13:29:20
An: Bruno Haible
Cc: [email protected]; Martin Uecker
Betreff: Re: clumsy cast in dlopen.3Hi Bruno,
Quoted 8 lines · Bruno Haible
The dlopen.3 man page contains this text:
*(void **) &cosine =
dlsym(handle, "cos");This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
I think I agree. Dereferencing the pointer &cosine with a type different than the type of the object is not allowed. I've CCed Martin, who might be able to confirm.
Quoted 8 lines
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u; u.pointer = dlsym(handle, "cos"); ... printf("%f\n", u.cosine(2.0));This is seems much better, indeed.
Have a lovely day!
AlexQuoted 6 lines
Bruno
Alejandro Colomar
maintainerHi Martin,
Quoted 6 lines · Martin Uecker
There is no such thing needed here, you just do
double (*cosine)(double);
cosine =
dlsym(handle, "cos");
Hmmmm, yes. I don't know why the manual page uses a cast in the POSIX version.
The above wouldn't be enough in ISO C, since void* isn't guaranteed to work with function pointers. However, any systems where dlsym(3) works must support holding function pointers in void* (because otherwise, dlsym(3) itself wouldn't work), so ISO C shouldn't be a concern at all.
Hmmm; I'll simplify the page.
Thanks!
Have a lovely day!
Alex
Quoted 108 lines
Best,
MartinAm Freitag, dem 15.05.2026 um 11:56 +0200 schrieb Alejandro Colomar:
Quoted 102 lines
Hi Walter,
Quoted 5 lines · Walter Harms
Hello,
I agree the cast is not nice, (someone for a extension of C standard ?) but i have to admit that i have never seen the trick with the union. But it needs some explaination. The comment in the example is already huge, i would ask for a comment subsektion for this behavier here.The thing about unions is that the only two ways for type punning that are blessed by ISO C are unions and memcpy(3). Everything else isn't allowed.
Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); union u {int i; float f;}; float f; union u u; u.i = 42; f = u.f;Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; memcpy(&f, &i, sizeof(float));UB:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; f = *(float *) &i;Have a lovely day!
AlexQuoted 53 lines
btw: the original code in the example looks like this ... cosine = (typeof(double (double)) *)
dlsym(handle, "cos");my2c
wh________________________________________
Von: Alejandro Colomar <[email protected]>
Gesendet: Donnerstag, 14. Mai 2026 13:29:20
An: Bruno Haible
Cc: [email protected]; Martin Uecker
Betreff: Re: clumsy cast in dlopen.3Hi Bruno,
Quoted 8 lines · Bruno Haible
The dlopen.3 man page contains this text:
*(void **) &cosine =
dlsym(handle, "cos");This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
I think I agree. Dereferencing the pointer &cosine with a type different than the type of the object is not allowed. I've CCed Martin, who might be able to confirm.
Quoted 8 lines
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u; u.pointer = dlsym(handle, "cos"); ... printf("%f\n", u.cosine(2.0));This is seems much better, indeed.
Have a lovely day!
AlexQuoted 6 lines
Bruno
Signature · 1 line
<https://www.alejandro-colomar.es>
Just for clarification, my comment was not about the patch itself. I was just expressing my fear that a comment discussing various complex topics will be added to the example and confusing future readers. I have notice that Bruno has send a patch removing most of the comments, i am happy with that outcome.
CU
________________________________________
Von: Alejandro Colomar <[email protected]>
Gesendet: Freitag, 15. Mai 2026 17:15:03
An: Martin Uecker
Cc: Walter Harms; Bruno Haible; [email protected]
Betreff: Re: AW: clumsy cast in dlopen.3
Hi Martin,
Quoted 6 lines · Martin Uecker
There is no such thing needed here, you just do
double (*cosine)(double);
cosine =
dlsym(handle, "cos");
Hmmmm, yes. I don't know why the manual page uses a cast in the POSIX version.
The above wouldn't be enough in ISO C, since void* isn't guaranteed to work with function pointers. However, any systems where dlsym(3) works must support holding function pointers in void* (because otherwise, dlsym(3) itself wouldn't work), so ISO C shouldn't be a concern at all.
Hmmm; I'll simplify the page.
Thanks!
Have a lovely day!
Alex
Quoted 108 lines
Best,
MartinAm Freitag, dem 15.05.2026 um 11:56 +0200 schrieb Alejandro Colomar:
Quoted 102 lines
Hi Walter,
Quoted 5 lines · Walter Harms
Hello,
I agree the cast is not nice, (someone for a extension of C standard ?) but i have to admit that i have never seen the trick with the union. But it needs some explaination. The comment in the example is already huge, i would ask for a comment subsektion for this behavier here.The thing about unions is that the only two ways for type punning that are blessed by ISO C are unions and memcpy(3). Everything else isn't allowed.
Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); union u {int i; float f;}; float f; union u u; u.i = 42; f = u.f;Perfectly valid:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; memcpy(&f, &i, sizeof(float));UB:
static_assert(sizeof(int) == sizeof(float)); int i; float f; i = 42; f = *(float *) &i;Have a lovely day!
AlexQuoted 53 lines
btw: the original code in the example looks like this ... cosine = (typeof(double (double)) *)
dlsym(handle, "cos");my2c
wh________________________________________
Von: Alejandro Colomar <[email protected]>
Gesendet: Donnerstag, 14. Mai 2026 13:29:20
An: Bruno Haible
Cc: [email protected]; Martin Uecker
Betreff: Re: clumsy cast in dlopen.3Hi Bruno,
Quoted 8 lines · Bruno Haible
The dlopen.3 man page contains this text:
*(void **) &cosine =
dlsym(handle, "cos");This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings.
However, such a cast violates the strict aliasing rules of ISO C, no?
I think I agree. Dereferencing the pointer &cosine with a type different than the type of the object is not allowed. I've CCed Martin, who might be able to confirm.
Quoted 8 lines
The proper workaround is to use a union:
union { double (*cosine) (double); void *pointer; } u; u.pointer = dlsym(handle, "cos"); ... printf("%f\n", u.cosine(2.0));This is seems much better, indeed.
Have a lovely day!
AlexQuoted 6 lines
Bruno
Alejandro Colomar
maintainerPATCH 1/1 man/man3/dlopen.3: EXAMPLES: Simplify use of dlsym(3)
In reply to Martin UeckerThe cast is entirely unnecessary. Conversion from/to void* and function pointers is implicit, and it's guaranteed by POSIX. ISO C is irrelevant here, because dlsym(3) requires POSIX, which provides the stronger guarantees that we need.
And even before POSIX standardized these guarantees about void* and function pointers, and system implementing dlsym(3) would have to support them anyway, as otherwise dlsym(3) couldn't work at all.
--- man/man3/dlopen.3 | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-)
man/man3/dlopen.3 +4 -16
@@ -567,23 +567,11 @@ .SS Program source \& dlerror(); /* Clear any existing error */ \& - cosine = (typeof(double (double)) *) dlsym(handle, "cos"); + cosine = dlsym(handle, "cos"); \& - /* According to the ISO C standard, casting between function - pointers and \[aq]void *\[aq], as done above, produces undefined results. - POSIX.1\-2001 and POSIX.1\-2008 accepted this state of affairs and - proposed the following workaround: -\& - *(void **) &cosine = dlsym(handle, "cos"); -\& - This (clumsy) cast conforms with the ISO C standard and will - avoid any compiler warnings. -\& - The 2013 Technical Corrigendum 1 to POSIX.1\-2008 improved matters - by requiring that conforming implementations support casting - \[aq]void *\[aq] to a function pointer. Nevertheless, some compilers - (e.g., gcc with the \[aq]\-pedantic\[aq] option) may complain about the - cast used in this program. */ + /* The 2013 Technical Corrigendum 1 to POSIX.1\-2008 + required that conforming implementations support + converting \[aq]void *\[aq] to a function pointer. */ .\" http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html#tag_03_112_08 .\" http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlsym.html#tag_16_96_07 .\" http://austingroupbugs.net/view.php?id=74
Range-diff against v0:
-: -------- > 1: 508bb497 man/man3/dlopen.3: EXAMPLES: Simplify use of dlsym(3)
Signature · 1 line
2.53.0
Re: [PATCH v1] man/man3/dlopen.3: EXAMPLES: Simplify use of dlsym(3)
The patch looks good to me. Thanks for removing the misleading comment!
Bruno
Alejandro Colomar
maintainerRe: [PATCH v1] man/man3/dlopen.3: EXAMPLES: Simplify use of dlsym(3)
Hi Bruno,
Quoted 1 line · Bruno Haible
The patch looks good to me. Thanks for removing the misleading comment!
You're welcome! Thanks for the report! I've taken your reply as an Acked-by tag in the patch.
Have a lovely night!
Alex
Quoted 4 lines
Bruno
Signature · 1 line
<https://www.alejandro-colomar.es>