Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c
Subject: Re: So You Think You Can Const?
Date: Mon, 13 Jan 2025 11:55:58 -0800
Organization: A noiseless patient Spider
Lines: 78
Message-ID: <86ldve5vzl.fsf@linuxsc.com>
References: <874j27qfp7.fsf@nosuchdomain.example.com> <20250110122353.00005377@yahoo.com> <20250112130744.00000118@yahoo.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Mon, 13 Jan 2025 20:55:59 +0100 (CET)
Injection-Info: dont-email.me; posting-host="9eea8443f476a77794ac96904ee9ae64";
logging-data="2119869"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/DOYphUoDCCKHLyk/6WKu8aPc0i408L6s="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:l84CToB0F29p2VMbmEsDBOqOakg=
sha1:n2Id0lW6hJ+DkzTdn04duNRRHFM=
Bytes: 4867
Michael S writes:
> On Fri, 10 Jan 2025 08:50:07 -0500
> James Kuyper wrote:
>
>> On 1/10/25 05:23, Michael S wrote:
>>
>>> On Thu, 09 Jan 2025 23:40:52 -0800
>>> Keith Thompson wrote:
>>
>> ...
>>
>>>> After the call to free(), the int object logically no longer
>>>> exists. Also, the value of the pointer object ptr becomes
>>>> indeterminate. Attempting to refer to the value of either ptr or
>>>> *ptr has undefined behavior.
>>>
>>> I believe that the Standard really says that, but find the part
>>> about value of ptr variable ridiculous. It breaks natural hierarchy
>>> by which standard library is somewhat special, but it is not above
>>> rules of core language. free() is defined as function rather than
>>> macro. By rules of core language, a function call can not modify
>>> the value of local variable at caller's scope, unless pointers to
>>> the variable was passed to it explicitly.
>>
>> And that applies to free() just as much as any user-defined function.
>>
>> Keep in mind that if p is a value returned by a call to a memory
>> management function (alloc_aligned(), malloc(), calloc() or
>> realloc()), the values of all pointers anywhere in the program that
>> point at any location in the block of memory allocated by the call to
>> that memory management function become indeterminate at the same
>> time. This doesn't mean that free() has permission to change the bit
>> pattern stored in any of those pointer objects. It doesn't. There's
>> no legal way to access the values stored in those objects; the only
>> thing you can do with those objects as a whole is to store a new
>> value in them. It is, however, legal to access the individual bytes
>> that make up the pointer's representation. Those bytes are themselves
>> objects, and changing the values stored in those bytes would
>> therefore violate 6.2.4p2: "An object exists, has a constant
>> address36) , and retains its last-stored value throughout its
>> lifetime."
>>
>> What the indeterminate value of those pointers does mean is that
>> implementations have permission to remove that entire block of memory
>> from the list of valid pointer locations. On a system which uses
>> memory maps, that can be as simple as modifying one entry in the
>> memory map table.
>>
>> By the way, this argument was controversial when I made it in a
>> discussion on this newsgroup in 2003 in a thread titled "pointer after
>> free indeterminate (your example James)". Yes, I am the "James" in
>> that title. You can look up that thread using Google Groups, if you
>> want to examine the arguments for and against. I don't believe that
>> there's been any relevant changes in the standard, but it's been two
>> decades and several revisions of the standard, so I could be wrong
>> about that.
>
> Tried to read the old discussion. Didn't understand much.
> But it strengthened my opinion: it's ridiculous. Standard would be way
> better with this nonsense removed.
> The function below should be guaranteed by standard to return 42.
> int foo(void)
> {
> char* a = malloc(100);
> if (!a) return 42;
> char* b = a + 42;
> free(a);
> return b - a;
> }
Imposing that requirement could mean assuming a level of
architectural support that some hardware doesn't provide.
Historically the decision made in the original C standard
was the most sensible choice available. Even though the
current description leaves something to be desired, it's
hard to find a compelling argument that the rule be changed
now.