Re: AW: clumsy cast in dlopen.3
From: Alejandro Colomar <alx@kernel.org>
Date: 2026-05-15 15:15:07
Hi Martin, On 2026-05-15T16:05:24+0200, Martin Uecker wrote:
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
Best, Martin Am Freitag, dem 15.05.2026 um 11:56 +0200 schrieb Alejandro Colomar:quoted
Hi Walter, On 2026-05-15T08:35:49+0000, Walter Harms wrote:quoted
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
btw: the original code in the example looks like this ... cosine = (typeof(double (double)) *) dlsym(handle, "cos"); my2c wh ________________________________________ Von: Alejandro Colomar [off-list ref] Gesendet: Donnerstag, 14. Mai 2026 13:29:20 An: Bruno Haible Cc: linux-man@vger.kernel.org; Martin Uecker Betreff: Re: clumsy cast in dlopen.3 Hi Bruno, On 2026-05-14T12:56:55+0200, Bruno Haible wrote:quoted
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
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
Bruno-- <https://www.alejandro-colomar.es>
-- <https://www.alejandro-colomar.es>
Attachments
- signature.asc [application/pgp-signature] 833 bytes