Path: ...!weretis.net!feeder9.news.weretis.net!news.quux.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Kaz Kylheku <643-408-1753@kylheku.com> Newsgroups: comp.lang.c Subject: Re: So You Think You Can Const? Date: Fri, 10 Jan 2025 19:28:22 -0000 (UTC) Organization: A noiseless patient Spider Lines: 66 Message-ID: <20250110111155.648@kylheku.com> References: Injection-Date: Fri, 10 Jan 2025 20:28:22 +0100 (CET) Injection-Info: dont-email.me; posting-host="04b5f0709b08f472ac875a8f159cacc9"; logging-data="220805"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX185LEL82IUII1jWAahEAwEsF08b0h5FCOY=" User-Agent: slrn/pre1.0.4-9 (Linux) Cancel-Lock: sha1:qzxunO1xbo6Q/SQa3V33kmuAZP8= Bytes: 3530 On 2025-01-09, David Brown wrote: > On 08/01/2025 17:48, Andrey Tarasevich wrote: > >> >> It is perfectly safe. One can even argue that standard declaration if >> `free` as `void free(void *)` is defective. It should have been `void >> free(const void *)` from the very beginning. > > It is common in simple heap implementations for the allocated block to > contain data about the block, such as allocation sizes and pointers to > other blocks, in memory just below the address returned by malloc. > free() then uses its parameter to access that data, and may change it. > So "void free(const void *);" would be lying to the user. If the pointer came from the allocator, as required, there is no lie. The object is writable, and so free may strip away the qualifier and do whatever it wants, like cover the object with 0xFE bytes. Quite contrary, if the program calls free(p), yet still somehow cares about what happens to the contents referenced by p, then the program is lying to the implementation! The prototype of free being: void free(const void *) would be helpful. It would mean that programs which choose to initialize dynamically allocated objects and then pass them around via pointers to const could then free the objects without having to use a cast. Code like this can be free of casts: const obj *obj_create(int param) { obj *o = malloc(sizeof *po); // null check omitted for topic focus o->param = param; return o; // after this, objs treated as immutable } void obj_destroy(const obj *o) { free(o); } Free of casts is good! Might it already be that the features of the current ISO C standard allow for the possibility of free being generic betwen const and unqualified? Though I don't suspect you can select on a pointer's referenced type's qualification, regardless of type. What are the backward compatibilty considerations of just making the prototype void free(const void *)? One is this problem: void (*pfree)(void *) = free; but in fact, the type rules should be such that the assignment is allowed even if free is void(const void *). The type compatibility rule should be that a function pointer type with more strictly qualified parameters should be implicitly convertible to a function pointer type with less strictly qualified parameters. -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal Mastodon: @Kazinator@mstdn.ca