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.