Path: csiph.com!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c
Subject: Re: *rubeyes*: realloc(ptr, 0) is UB?
Date: Sun, 21 Jan 2024 06:55:03 -0800
Organization: A noiseless patient Spider
Lines: 68
Message-ID: <86plxuhh2w.fsf@linuxsc.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> <877ck5c8dl.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="92215711b06d8c3aeb5738d6959250bf"; logging-data="243442"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/lO/0kd/c93HJvR9wWHzSVM0moS0NZvcQ="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:84Xka+0OAVpusi5P5YpHeO+dUrQ= sha1:Q8SWFeJg9KCocYVvSN9BpaOydwg=
Xref: csiph.com comp.lang.c:380570
Keith Thompson writes:
[.. considering the definition of malloc(0) ..]
> I dislike the fact that the behavior is currently
> implementation-defined. I think requiring malloc(0) to return a
> null pointer would be an improvement over the current (C11)
> specification, though it would be an odd special case; a null
> pointer would mean either that the allocation failed (and the
> system is likely in a bad state) or that the requested size was 0.
> Note that an application might call malloc() with a variable
> argument whose value can just happen to be zero. [...]
First I think it is worth going back and re-reading the Rationale
where it talks about malloc() and friends.
I'm sympathetic to the reaction about malloc() and friends having
different behavior in different implemenations. On the other
hand let's look at it from the point of view of implementations:
(A) For malloc(0) returning non-null: that can be a convenience
for some applications, and can be supplied in a way that client
code cannot provide.
(B) For malloc(0) returning null: most programs don't allocate
zero-sized objects, except perhaps inadvertently; in most uses
code will work without needing to distinguish, and in those cases
where the distinction is important it isn't hard to write code
that works for both allowed behaviors; being able to return null
for zero-size requests both simplifies the code and uses less
resource than choice (A). In small systems the added resource
demands may very well be the deciding factor between choosing (A)
and choosing (B).
For most aspects, client code can ignore the distinction between
behavior (A) and behavior (B). The big exception to that is how
to detect errors. If we think the C standard should continue to
allow both possibilities (and personally I think it should), a
way around the problem is to provide a testable macro symbol, as
for example
#if __MALLOC_0_GIVES_NULL
...
#elif __MALLOC_0_GIVES_NONNULL
...
#else
... deal with uncertainty in some way
... (not hard although it may involve a run-time cost)
#endif
If some such macros were provided it isn't hard to define a macro
that does error checking in both kinds of environments, so there
could be code like this:
Foo *p = malloc( n * sizeof *p );
if( MALLOC_FAILED( p, n ) ) ...
where the MALLOC_FAILED() macro would either simply test '!p' or
would test '!p && n > 0', depending on whether the code is
running in an (A) regime or a (B) regime.
Personally I would like to see the memory allocation functions
augmented to be explicit about which behavior is wanted:
void *malloc0( size_t ); /* returns NULL for size of 0 */
void *malloc1( size_t ); /* returns NULL only on failure */
along with analogous changes for calloc(), realloc(), etc.