Path: csiph.com!news.mixmin.net!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: "Catch-23: The New C Standard,Sets the World on Fire" by Terence Kelly with Special Guest Borer Yekai Pan Date: Wed, 05 Apr 2023 10:40:01 -0700 Organization: None to speak of Lines: 112 Message-ID: <87mt3mgrda.fsf@nosuchdomain.example.com> References: <87zg7n89zw.fsf@bsb.me.uk> <874jpv84uv.fsf@bsb.me.uk> MIME-Version: 1.0 Content-Type: text/plain Injection-Info: dont-email.me; posting-host="9e2405598efc68074ee4f991f6edbed6"; logging-data="4183699"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/pm7RDvCmkjFeY/L7RlGv1" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:sm/42lW7pCrpOq03FFft3cUmTyk= sha1:YlWq6vb7jcdszsxg5EYOtYI9Yr8= Xref: csiph.com comp.lang.c:169837 David Brown writes: > On 05/04/2023 15:29, Dan Cross wrote: >> In article <874jpv84uv.fsf@bsb.me.uk>, >> Ben Bacarisse wrote: > >>> I got the impression they knew that. However, in C89, realloc(ptr, 0) >>> must behave like free(ptr). That changed, I think, in C99 with the >>> removal of that guarantee. There is some evidence that they are little >>> confused about that guarantee having been lost, thought of course it is >>> still permitted. >> Indeed, you are correct. From C89, 7.10.3.3: "if *size* is zero >> and *ptr* is not a null pointer, the object it points to is >> freed." > > I don't have a C89 reference handy, but I don't think realloc(ptr, 0) > has ever been required to behave like free(ptr). That is one of the > allowed behaviours, but it is not the only one. In particular, even > if it first acts like free(ptr), it can then allocate a zero-size > buffer afterwards. Thus it may not be behaving like free(ptr) alone - > it can do more. And if you don't take that into account, your code > will leak memory. ISO C90: 7.10.3 Memory management functions [...] If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined; the value returned shall be either a null pointer or a unique pointer. ... 7.10.3.4 The realloc function Synopsis #include void *realloc(void *ptr, size_t size); Description The `realloc` function changes the size of the object pointed to by `ptr` to the size specified by `size`. The contents of the object shall be unchanged up to the lesser of the new and old sizes. If the new size is larger, the value of the newly allocated portion of the object is indeterminate. If `ptr` is a null pointer, the `realloc` function behaves like the `malloc` function for the specified size. Otherwise, if `ptr` does not match a pointer earlier returned by the `calloc`, `malloc`, or `realloc` function, or if the space has been deallocated by a call to the `free` or `realloc` function. the behavior is undefined. If the space cannot be allocated, the object pointed to by `ptr` is unchanged. If `size` is zero and `ptr` is not a null pointer, the object it points to is freed. Returns The `realloc` function returns either a null pointer or a pointer to the possibly moved allocated space. ISO C99 expands the "Memory management functions" description: If the size of the space requested is zero, the behavior is implementation- defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object. Where C90 says that realloc changes the size of the object, C99 says that it deallocates the old object and allocates a new one. This isn't a change in behavior, but it more accurately describes what's going on. If `ptr` is a null pointer, the `realloc function behaves like the `malloc` function for the specified size. Otherwise, if `ptr` does not match a pointer earlier returned by the `calloc`, `malloc`, or `realloc` function, or if the space has been deallocated by a call to the `free` or `realloc` function, the behavior is undefined. If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged. Returns The `realloc` function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated. C11 makes a few minor changes (adding references to aligned_alloc and "fundamental alignment requirement"). C17 makes a few minor changes, but nothing relevant to the current discussion. C23 (N3096 draft) makes some more changes: Any bytes in the new object beyond the size of the old object have [indeterminate->unspecified] values. Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free or realloc function, [+or if the size is zero+], the behavior is undefined. References: C99 draft: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf C11 draft: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf C23 draft: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for XCOM Labs void Void(void) { Void(); } /* The recursive call of the void */