Thread (10 messages) 10 messages, 4 authors, 5d ago

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!
Alex
quoted
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!
Alex
quoted
Bruno


--
<https://www.alejandro-colomar.es>
-- 
<https://www.alejandro-colomar.es>

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help