realloc
¶POSIX specification:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/realloc.html
Portability problems fixed by Gnulib:
errno
:
mingw, MSVC 14.
errno
to EAGAIN
instead of to ENOMEM
. Although POSIX allows
EAGAIN
, the realloc-posix
module insists on ENOMEM
which also conforms to POSIX and is GNU-compatible:
Solaris 11.4.
realloc (p, n)
can succeed even if n
exceeds PTRDIFF_MAX
. Although this behavior is arguably
allowed by POSIX it is not compatible with GNU and
can lead to behavior not defined by POSIX later,
so realloc-posix
does not allow going over the limit.
realloc
with a size of 0.
With a null pointer argument, this is the same ambiguity as malloc (0)
as to whether a successful call returns a null pointer or a pointer to a
new zero-sized memory region. Although both behaviors conform to POSIX,
realloc-posix
insists on the latter behavior, which is
compatible with GNU.
With non-null p
, behavior is a real mess for realloc (p, 0)
.
C23 says behavior is undefined.
C89 through C17 say a successful call returns either a null pointer
or a pointer to a new zero-sized memory region.
POSIX.1-2017 extends C99 by saying that if a successful call
returns a null pointer it
must also set errno
to an implementation-defined value,
and POSIX.1-2024 extends C17 a bit further by saying that
such a call must set errno
to EINVAL
.
It is not known what POSIX.1-2024’s successor will say,
though presumably it will extend C23.
In practice, successful realloc (p, 0)
calls
have one of the following behaviors:
p
, do not change errno
, and return a null pointer:
glibc 2.33–2.40 by default, Android.
p
, possibly set errno
, and return a null pointer:
glibc 1–2.1 if specially built with REALLOC_ZERO_BYTES_FREES=1
,
glibc 2.1.1–2.32 by default,
mingw, MSVC 14.
p
, set errno
to EINVAL
, and return a null pointer:
AIX 7.3 without _LINUX_SOURCE_COMPAT
.
p
and return a pointer to a new region of size zero:
AIX 7.3 with _LINUX_SOURCE_COMPAT
, glibc 1–2.1 by default,
glibc 2.1.1–2.40 if specially built with REALLOC_ZERO_BYTES_FREES=0
,
musl libc, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, Cygwin.
Behaviors (3) and (4) conform to POSIX; behaviors (1) and (2) do not.
The realloc-posix
module insists on behavior (4) as it is more
popular than (3) and is more useful in practice. Behavior (4) is the
only one of the four in which returning a null pointer means failure,
which is what non-expert programmers typically expect.
A program not suspecting these variations in semantics will either:
p
) if it unwisely does not check
for realloc
failure, when it assumes behavior (1), (2) or (3) but the
system implements behavior (4).
realloc
failure), or have double-free bugs (if it unwisely does not check),
when it assumes behavior (4) but the system implements (1), (2) or (3).
realloc (p, 0)
sets errno to EINVAL
and returns null,
a POSIX.1-2024 application cannot tell whether the call has succeeded
and freed p
, or has failed without freeing p
.
This is only a theoretical problem, though, as the only practical
implementation with this behavior is AIX without _LINUX_SOURCE_COMPAT
,
which behaves this way only when the call succeeds.
Portability problems not fixed by Gnulib:
p
points to a region of size psize
and n <= psize
,
realloc (p, n)
can fail and return a null pointer:
glibc 2.40 and probably other platforms.