On 2025-06-19 11:31, Eric Blake wrote:
glibc folks are aware that realloc(non_null, 0) has two useful behaviors,
and that glibc picks the behavior that does NOT behave consistently
with malloc(0), because of back-compat guarantees:
Thanks for the detailed summary. Here are a few more details. In this
summary "realloc(p,0)" assumes p is nonnull.
As I understand it:
(a) These guarantees are for compatibility with glibc 2.2+. In older
glibc versions realloc(p,0) behaved like (free(p),malloc(0)).
(b) Ulrich Drepper changed glibc 2.2 realloc(p,0) after Andreas Jaeger
told him[1] that draft C99 and UNIX98 required realloc(p,0) to free(p).
Conformance to these standards was the only motivation given for the
glibc change.
(c) Ulrich's change[2] to glibc was to make realloc(p,0) equivalent to
(free(p),0). Draft C99 and UNIX98 did not require this, and Ulrich could
have made realloc(p,0) continue to be equivalent to (free(p),malloc(0)).
The email thread for [1] indicates that people were confused about what
C89/C99 and UNIX98 required; people seemed to think mistakenly that, for
example, a somewhat-perverse implementation where realloc(p,0) always
returns p would not conform to C89/C99 and UNIX98.
getting a specification that people are happy with is difficult.
The disagreement mostly came from two camps many years ago. One camp
(call it "traditional") wanted zero-size allocations a la 7th Edition
UNIX; the other camp (call it "SysV") wanted malloc(0) and
realloc(...,0) to fail (ideally with errno==EINVAL) because zero-sized
objects are problematic in C.
Although the traditional camp mostly won in practice, the SysV camp
arranged for POSIX to allow either traditional or SysV behavior without
requiring the implementation's behavior to be consistently traditional
or consistently SysV. This has resulted in a POSIX spec that seems to be
getting more confusing in each iteration, with POSIX.1-2024 prohibiting
current glibc behavior (apparently by accident).
[1]: https://sourceware.org/pipermail/libc-alpha/1999-April/000956.html
[2]:
https://github.com/bminor/glibc/commit/7c2b945e1fd64e0a5a4dbd6ae6592a7314dcd4b5