Path: csiph.com!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: *rubeyes*: realloc(ptr, 0) is UB? Date: Sun, 21 Jan 2024 15:04:13 -0800 Organization: None to speak of Lines: 88 Message-ID: <87edeab85u.fsf@nosuchdomain.example.com> References: <20240116162506.143@kylheku.com> <20240117094759.508@kylheku.com> <9iYpN.354613$83n7.275953@fx18.iad> <86r0ifjbiw.fsf@linuxsc.com> <20240118112920.465@kylheku.com> <20240118144021.3@kylheku.com> <87r0iech8j.fsf@nosuchdomain.example.com> <87msszbb08.fsf@nosuchdomain.example.com> <86cytugvve.fsf@linuxsc.com> MIME-Version: 1.0 Content-Type: text/plain Injection-Info: dont-email.me; posting-host="9cd31264156fc70cf12828e27041ba36"; logging-data="438581"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Cf0w+8vakM0+1jTnJSyiZ" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:UHPUR7N8cmF94tm+cFhF+bEVjCs= sha1:/itDTcR7yDOBNr5M0MSL2dTQh4U= Xref: csiph.com comp.lang.c:380593 Tim Rentsch writes: > Keith Thompson writes: >> Keith Thompson writes: >>> Kaz Kylheku <433-929-6894@kylheku.com> writes: >>>> On 2024-01-18, James Kuyper wrote: >>>>> It's OK to rely upon the requirements imposed by an implementation when >>>>> the C standard doesn't impose any - but when you do so, you need to make >>>>> sure you actually know what those requirements are. >>>> >>>> Exactly, and in this specific case, it's not worth the effort compared >>>> to writing a realloc wrapper that avoids the undefined behavior, while >>>> itself providing a C99 conforming one. >>>> >>>> I'm not going to use realloc(ptr, 0) and check everyone's documentation. >>>> >>>> And then what if I don't find it defined? The what? Back to the >>>> wrapper I could have just written in the first place. >>> >>> [...] >>> >>> I think I would have *liked* to see C23 drop the special permission >>> to return a null pointer for a requested size of zero. C11 says (and >>> this applies to malloc, realloc, and all other allocation 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: 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. >>> >>> This could have been changed to: >>> >>> If the space cannot be allocated, a null pointer is returned. If >>> the size of the space requested is zero, the behavior is as >>> if the size were some nonzero value, except that the returned >>> pointer shall not be used to access an object. >>> >>> Any existing implementations that always return a null pointer >>> for malloc(0) would have to be updated. That shouldn't be a >>> great burden. >>> >>> Note that malloc(0) or realloc(ptr, 0) can still fail and return >>> a null pointer if no space can be allocated, so all allocations >>> should still be checked. But with this proposed change, code >>> could rely on realloc(ptr, 0) returning a non-null pointer *unless* >>> available memory is critically low -- pretty much the same as in C11, >>> except that a null pointer would be an indication that something >>> is seriously wrong. >>> >>> (I remember seeing a discussion about making the behavior of >>> realloc(ptr, 0) undefined. I'm making inquiries, and I'll follow >>> up if I learn anything relevant.) >> >> I got a response from JeanHeyd Meneide. >> >> If realloc(ptr, 0) returns a null pointer there's no way to tell whether >> allocation failed (and ptr has not been freed), or the implementation >> returns a null pointer for zero-sized allocations (and ptr has been >> freed). Some implementations set errno, but C doesn't require it. > > It's trivial to fix that problem: simply require implementations > to define a preprocessor symbol about how the implementation > works. Problem solved. > > (There are other instances of implementation-defined behavior > that would benefit from analogous changes along these lines.) I tend to agree that such a preprocessor symbol would be an improvement. I still think, as I wrote above, that removing the permission to return a null pointer on a successful zero-sized allocation would be a greater improvement. A preprocessor symbol makes it easier for programmers to work around the potential difference between implementations. The change I advocate would make it completely unnecessary. Except, of course, that most code would still have to allow for pre-C26 behavior, even if the change were adopted in C26. That's unavoidable in the absence of time machines. On the gripping hand, since it seems that most existing implementations (well, all of the few I've tried) return a non-null pointer for malloc(0), it might be reasonable to ignore the few pre-C26 implementations that return a null pointer. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Medtronic void Void(void) { Void(); } /* The recursive call of the void */