According to the change log of C23, proposal n2464 was voted-in and implemented, making realloc(ptr, 0)
explicitly undefined behavior, whereas it was supposedly implementation-defined in previous standards. In the drafts (quotes are from n3096), the specification of realloc
has been changed accordingly: (bold emphasis mine)
7.24.3.7 The realloc function
/--/
...or if thesize
is zero, the behavior is undefined
However, in the C23 drafts we can also read:
7.24.3 Memory management functions
/--/
If the size of the space requested is zero, the behavior is implementation-defined
Annex J.1 Unspecified behavior
(46) The amount of storage allocated by a successful call to the calloc, malloc, realloc, or aligned_alloc function when 0 bytes was requested (7.24.3).
Annex J.2 Undefined behavior
(179) A non-null pointer returned by a call to the calloc, malloc, realloc, or aligned_alloc function with a zero requested size is used to access an object (7.24.3).
Annex J.3.12 Implementation-defined behavior
(42) Whether the calloc, malloc, realloc, and aligned_alloc functions return a null pointer or a pointer to an allocated object when the size requested is zero (7.24.3).
Now, I did try to point out this defect to the ISO C WG through informal channels, but to deaf ears evidently, since the defects are still there in draft n3220. 7.24.3.7 and 7.24.3 are both normative texts, whereas Annex J is informative (and already filled to the brim with errors even before C23, never to be trusted). So which of the contradicting texts is "most normative"?
May old programs with realloc(ptr, 0)
get ported to C23 and the same implementation-defined behavior might still be there? Or will such code be non-portable to C23 since it invokes UB? Or will this remain a defect after publication and we have to wait for a TC to get published?
realloc()
is an 'all-in-one' memory management function. It can allocate memory, shrink already allocated memory, expand already allocated memory, or free already allocated memory — so why bother withmalloc()
orfree()
. It isn't completely clear that the C standard fully approved this, but it was close to reality on many systems. The general direction (intention) has been to tighten up the semantics.free(0)
is a nice feature offree()
, else users need to codeif (ptr) free(ptr)
. Re-defining ID behavior ofrealloc(ptr, 0)
to UB is a wrong direction and makes for more complex (and more error prone) usage ofrealloc()
as well asmalloc()
. Just leave (re-)allocation of zero as ID behavior and stop breaking existing code bases for little, if any gain.