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.