Path: csiph.com!weretis.net!feeder8.news.weretis.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: Tue, 23 Jan 2024 19:28:38 -0800
Organization: A noiseless patient Spider
Lines: 79
Message-ID: <86r0i7e7fd.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> <87msszbb08.fsf@nosuchdomain.example.com> <86cytugvve.fsf@linuxsc.com> <87edeab85u.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="081b48eb4d739c8d0f1cd5168e73e868"; logging-data="1757645"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+WWIhSNIBtMlOJERy8bCY79GnVURJHRQY="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:72sy6VJEy+p5DLCjytoHPbjugnM= sha1:ySD05aZXN/8GdYaqoGvxZoUhO7I=
Xref: csiph.com comp.lang.c:380748
Keith Thompson writes:
> Tim Rentsch writes:
>
>> Keith Thompson writes:
>>
>>> Keith Thompson writes:
[...]
>>>> I think I would have *liked* to see C23 drop the special permission
>>>> to return a null pointer for a requested size of zero. C11 says (and
>>>> this applies to malloc, realloc, and all other allocation functions):
>>>> [...]
>>>>
>>>> Note that malloc(0) or realloc(ptr, 0) can still fail and return
>>>> a null pointer if no space can be allocated, so all allocations
>>>> should still be checked. But with this proposed change, code
>>>> could rely on realloc(ptr, 0) returning a non-null pointer *unless*
>>>> available memory is critically low -- pretty much the same as in C11,
>>>> except that a null pointer would be an indication that something
>>>> is seriously wrong.
>>>>
>>>> (I remember seeing a discussion about making the behavior of
>>>> realloc(ptr, 0) undefined. I'm making inquiries, and I'll follow
>>>> up if I learn anything relevant.)
>>>
>>> I got a response from JeanHeyd Meneide.
>>>
>>> If realloc(ptr, 0) returns a null pointer there's no way to tell
>>> whether allocation failed (and ptr has not been freed), or the
>>> implementation returns a null pointer for zero-sized allocations
>>> (and ptr has been freed). Some implementations set errno, but C
>>> doesn't require it.
(Let me mention in passing that there is a way to tell that
should work in practice on any non-malicious implementation.)
>> It's trivial to fix that problem: simply require implementations
>> to define a preprocessor symbol about how the implementation
>> works. Problem solved.
>>
>> (There are other instances of implementation-defined behavior
>> that would benefit from analogous changes along these lines.)
>
> I tend to agree that such a preprocessor symbol would be an
> improvement.
>
> I still think, as I wrote above, that removing the permission to
> return a null pointer on a successful zero-sized allocation would
> be a greater improvement.
>
> A preprocessor symbol makes it easier for programmers to work
> around the potential difference between implementations. The
> change I advocate would make it completely unnecessary.
>
> Except, of course, that most code would still have to allow for
> pre-C26 behavior, even if the change were adopted in C26. That's
> unavoidable in the absence of time machines. On the gripping
> hand, since it seems that most existing implementations (well, all
> of the few I've tried) return a non-null pointer for malloc(0), it
> might be reasonable to ignore the few pre-C26 implementations that
> return a null pointer.
I have an observation worth mentioning. Using glibc (tested in
Ubuntu), these assignments
void *x = malloc( 0 );
void *y = malloc( 1 );
both return a non-null pointer. Following that, however, these
calls
void *xx = realloc( x, 0 );
void *yy = realloc( y, 0 );
both return a null pointer, and subsequent code shows that both x
and y have indeed been deallocated. (Both gcc and clang give the
same result, which isn't surprising since both are using glibc.)