|
|
Subscribe / Log in / New account

Honestly kind of irrelevant

Honestly kind of irrelevant

Posted Oct 29, 2024 8:38 UTC (Tue) by chris_se (subscriber, #99706)
Parent article: realloc() and the oversize importance of zero-size objects

To me this is kind of irrelevant. If you want to write portable code then you have to cope with the fact that malloc(0) and realloc(ptr, 0) don't react the same on all platforms - and just avoid them altogether. To me any C code relying on these kind of specific behaviors (be that of glibc or any other platform) has a strong smell.

Even if the code is used in non-portable programs that are designed for just a single operating system, I still don't like them. There are some implementation-defined behaviors (such as relying on two's complement or 8bit byte sizes) where it can make a lot of sense to rely on those, because not assuming that would make the code a **lot** more complicated for no benefit at all in many cases. (And platforms that that don't use e.g. two's complement are extremely rare nowadays.) But avoiding malloc(0) or realloc(ptr, 0) is just 1-2 more lines of code. And if it's handled explicitly it is 100% clear what the code intends to do. In the absence of explicit handling that's not the case, and then one doesn't immediately know whether the code actually relies on that behavior, or whether there's a bug in there and the author didn't even think about that corner case.

I personally would leave the current behavior as-is, because I don't see any benefit of changing it, because in my opinion nobody should ever write new code that relies on these kinds of specifics. But I also don't really care if they do decide to change that behavior.


to post comments

Honestly kind of irrelevant

Posted Oct 29, 2024 10:10 UTC (Tue) by Wol (subscriber, #4433) [Link] (1 responses)

> To me this is kind of irrelevant. If you want to write portable code then you have to cope with the fact that malloc(0) and realloc(ptr, 0) don't react the same on all platforms - and just avoid them altogether. To me any C code relying on these kind of specific behaviors (be that of glibc or any other platform) has a strong smell.

I know this sort-of goes against the grain of being a standard, but why not say "here are two competing versions, you have to provide both (with a compiler switch), but we take no position on the default".

Khim's point about ISO saying Posix can do what it likes, when Posix explicitly defers to ISO, does imho appear daft. And if you want ISO C to be portable, specifying the two dominant (Posix and MS) implementations and saying "support both" seems to be the right way to go ... whether others agree is another matter ...

Cheers,
Wol

Honestly kind of irrelevant

Posted Oct 31, 2024 18:10 UTC (Thu) by NYKevin (subscriber, #129325) [Link]

Because you don't need to. The developer can just do this:

#define malloc_s(size) (size == 0? (void*)NULL : malloc(size))
#define realloc_s(ptr, size) (size == 0 ? free(ptr), (void*)NULL : realloc(ptr, size))

And then the compiler can optimize that back into a malloc/realloc call easily enough, if it knows that malloc/realloc have the appropriate semantics on a given platform.

Getting unique non-dereferencable pointers is harder, and IMHO should not be done, because (as I've explained elsewhere in the thread) it is cheaper to have a global u64 and atomically increment it (malloc takes a lock in almost any sensible implementation). If you somehow manage to allocate over 16 quintillion numbers in this fashion (so that it wraps), then you probably should be using UUIDs instead of 64-bit integers in the first place.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds