public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* free(3) const void *
@ 2024-01-26 13:21 Alejandro Colomar
  2024-01-26 14:24 ` Arsen Arsenović
                   ` (4 more replies)
  0 siblings, 5 replies; 33+ messages in thread
From: Alejandro Colomar @ 2024-01-26 13:21 UTC (permalink / raw)
  To: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 2722 bytes --]

Hi,

ISO C and POSIX say that free(3) shall take a `void *`.  But free() does
nothing to the pointee during its lifetime.  Of course, the lifetime of
the object ends right at the boundary of the call to free() itself.  And
even if the lifetime of the object would be extended to the end of
free(), it doesn't really modify the pointee internally; it only uses
the pointer to know which memory it is freeing, but never writes to it.
And even if some implementation would want to write to it for some
reason, it'd be as easy as discarding `const` internally.

It is sometimes (often?) useful to allocate some object, write
immediately to it, and then use it read-only.  The standard definition
of free() forces the programmer to keep a non-const pointer around just
for the sake of freeing, which is unnecessarily dangerous.

Since a `const void *` will accept anything that a `void *` would accept
(and more), how about changing the prototype of free() in glibc as an
extension to the language?

I'd like to refor free(3) to be:

	void free(const void *p);

But this would break function pointers.  I don't know if there's any way
to avoid that.  What was done when const was added to string functions?
Was it considered an acceptable breaking change?

	$ cat fp.c 
	#include <stdlib.h>

	typedef void (*free_t)(void *p);

	extern void free_const(const void *p);

	int
	main(void)
	{
		free_t  fp;

		fp = free;
		fp = free_const;
	}
	$ cc -Wall -Wextra fp.c 
	fp.c: In function ‘main’:
	fp.c:13:12: warning: assignment to ‘free_t’ {aka ‘void (*)(void *)’} from incompatible pointer type ‘void (*)(const void *)’ [-Wincompatible-pointer-types]
	   13 |         fp = free_const;
	      |            ^
	fp.c:10:17: warning: variable ‘fp’ set but not used [-Wunused-but-set-variable]
	   10 |         free_t  fp;
	      |                 ^~
	/usr/bin/ld: /tmp/ccVlhr05.o: in function `main':
	fp.c:(.text+0x12): undefined reference to `free_const'
	collect2: error: ld returned 1 exit status

Maybe we could add a function-like macro so that direct calls with a
`const` pointer use the macro and don't get a warning, but one can still
take the address of the function and it will use the standard prototype:

	$ cat fp.c 
	#include <stdlib.h>
	#include <string.h>

	typedef void (*free_t)(void *p);

	#define free(p)  free((void *) &*p)

	int
	main(void)
	{
		free_t      fp;
		const char  *s = strdup("foo");

		fp = free;
		(void) fp;
		free(s);
	}
	$ cc -Wall -Wextra fp.c 
	$

Does this sound reasonable?

Cheers,
Alex

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2024-02-13 15:28 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-26 13:21 free(3) const void * Alejandro Colomar
2024-01-26 14:24 ` Arsen Arsenović
2024-01-26 15:35   ` Alejandro Colomar
2024-01-26 17:22     ` Arsen Arsenović
2024-01-26 17:55       ` Xi Ruoyao
2024-01-26 18:11         ` Alejandro Colomar
2024-01-26 20:04           ` Arsen Arsenović
2024-01-26 20:07         ` Arsen Arsenović
2024-01-26 17:40     ` Andreas Schwab
2024-01-26 19:45     ` Florian Weimer
2024-01-26 15:13 ` Andreas Schwab
2024-01-26 15:33   ` Alejandro Colomar
2024-01-26 18:09 ` Russ Allbery
2024-01-26 18:23   ` Alejandro Colomar
2024-01-26 18:36     ` Xi Ruoyao
2024-01-26 18:40       ` Alejandro Colomar
2024-01-26 18:49         ` Xi Ruoyao
2024-01-26 18:57           ` Alejandro Colomar
2024-01-26 18:40     ` Russ Allbery
2024-01-26 18:45       ` Alejandro Colomar
2024-01-26 19:41   ` Florian Weimer
2024-01-26 18:39 ` [PATCH] Use [[gnu::access(none)]] on free(3) Alejandro Colomar
2024-01-26 18:41   ` Alejandro Colomar
2024-01-26 21:23     ` Paul Eggert
2024-01-26 23:19       ` Alejandro Colomar
2024-01-27 13:21       ` Cristian Rodríguez
2024-02-13 15:19         ` Gabriel Ravier
2024-02-13 15:28           ` Alejandro Colomar
2024-01-26 21:11 ` free(3) const void * DJ Delorie
2024-01-26 21:30   ` Andreas Schwab
2024-01-26 21:47     ` DJ Delorie
2024-01-26 22:07       ` Andreas Schwab
2024-01-26 23:25       ` Alejandro Colomar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).