17

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 the size 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?

24
  • 1
    You've missed the boat for public comments on C23 now.
    – Ian Abbott
    Commented Jul 1 at 11:37
  • 2
    @thebusybee With some luck it reaches the ears of the right person. Or perhaps this is a known DR, I wouldn't know.
    – Lundin
    Commented Jul 1 at 13:12
  • 2
    @IanAbbott The main issue is that 7.24.3 and 7.24.3.7 contradict each other.
    – Lundin
    Commented Jul 1 at 14:12
  • 3
    As Steven Maguire pointed out in Writing Solid Code: 20th Anniversary 2nd Edn (2013), it used to be that 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 with malloc() or free(). 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. Commented Jul 1 at 15:40
  • 3
    IMO: Well defined free(0) is a nice feature of free(), else users need to code if (ptr) free(ptr). Re-defining ID behavior of realloc(ptr, 0) to UB is a wrong direction and makes for more complex (and more error prone) usage of realloc() as well as malloc(). Just leave (re-)allocation of zero as ID behavior and stop breaking existing code bases for little, if any gain. Commented Jul 1 at 16:22

0

Browse other questions tagged or ask your own question.