6 ms·
Ages ago I worked with a system where malloc(0) incremented a counter and returned -1. free(-1) decremented the counter. This way you could check for leaks :p
by bobmcnamara 1y ago
Ages ago I worked with a system where malloc(0) incremented a counter and returned -1.
free(-1) decremented the counter.
This way you could check for leaks :p
- o11c 1y agoNoncompliant, since `malloc(0)` is specified to return a unique pointer if it's not `NULL`. On most platforms an implementation could just return adjacent addresses from the top half of the address space. On 32-bit platforms it doesn't take long to run out of such address space however, and you don't want to waste the space for a bitmap allocator. I suppose you could just use a counter for each 64K region or something, so you can reuse it if the right number of elements has been freed ...
- LPisGood 1y agoNoncompliant, but what could this reasonably impact?
- bobmcnamara 1y ago> Noncompliant, since `malloc(0)` is specified to return a unique pointer if it's not `NULL`. I know I've seen that somewhere, but may I ask what standard you're referring to?
- masfuerte 1y agoIt's POSIX. > Each [...] allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer shall be returned. If the size of the space requested is 0, the behavior is implementation-defined: either a null pointer shall be returned, or the behavior shall be as if the size were some non-zero value, except that the behavior is undefined if the returned pointer is used to access an object. https://pubs.opengroup.org/onlinepubs/9799919799/functions/malloc.html https://pubs.opengroup.org/onlinepubs/9799919799/functions/m...
- MaxBarraclough 1y agoNot just POSIX, also the ISO C standard itself. https://en.cppreference.com/w/c/memory/malloc https://en.cppreference.com/w/c/memory/malloc
- masfuerte 1y agoThat doesn't say the pointer has to be unique.
- jcranmer 1y agocppreference isn't the standard, and while the text they write looks like it's the same verbiage that would be authoritative, it's not. (And there's some criticism of it from standards committee members in that regard). The current C standard text says: > The order and contiguity of storage allocated by successive calls to the aligned_alloc, calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it can be assigned to a pointer to any type of object with a fundamental alignment requirement and size less than or equal to the size requested. It can then be used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object. So yeah, the allocations are required to be unique (at least until it's free'd).
- bobmcnamara 1y ago> Each such allocation shall yield a pointer to an object disjoint from any other object. Phrasing could be slightly more clear to prevent someone from making the argument that -1 is disjoint from all objects as it does not point to an object
- o11c 1y agoPointers are frequently used as keys for map-like data structures. This introduces collisions that the programmer can't check for, whereas NULL is very often special-cased.
- bobmcnamara 1y ago> Noncompliant, since `malloc(0)` is specified to return a unique pointer if it's not `NULL`. I know I've seen that somewhere, but may I ask what standard you're referring to? If I recall correctly, this was an archaic stackless microcontroller. The heap support was mostly a marketing claim.
- jmgao 1y agoC89: https://port70.net/%7Ensz/c/c89/c89-draft.html https://port70.net/%7Ensz/c/c89/c89-draft.html If the size of the space requested is zero, the behavior is implementation-defined; the value returned shall be either a null pointer or a unique pointer.
- f1shy 1y agoIsn’t -1 basically 0xffff which is a constant pointer? What am I missinterpreting?
- comex 1y agoIf you call malloc(0) multiple times (without freeing in between) and get -1 each time, then the pointer is not unique.
- deleted 1y ago[deleted]
- bobmcnamara 1y agoBut do we need a unique pointer or merely a pointer that is disjoint from all objects?
- david-gpu 1y agoAs per the specification, it has to be a unique pointer. Being tasked to implement a specification typically means having to pass extensive conformance tests and having to answer for instances of noncompliance. You soon learn to follow the spec to the letter, to the best of your abilities, unless you can make a strong case to your management for each specific deviation.
- j1elo 1y agoOh but no worries with compliance, it always returned a newly created -1, never repeating the same one!
- hun3 1y agoMy next malloc(3) is returning NAN.
- fredfish 1y agoI've always considered NaN too definitive for general industry languages like C, JS or Cobol where not even physics with calculus should be assumed. Maybe its ok for languages that at least expect math for engineers like Fortran or up.. How about we call it "Maybe a Number" and since equality can't work for it we still need a separate way to ask like: Math.whoIsTheMaN(me)
- sgerenser 1y agoI might be missing something, but how does this help in checking for leaks? I mean, I guess you could use it to check for leaks specifically of 0-sized allocations, but wouldn’t it be better just to return NULL and guarantee that 0-sized allocations never use any memory at all?
- bobmcnamara 1y agoAt the end of main, if the count wasn't balanced, then you knew you had a mismatch between malloc()/free(). If malloc() had returned a real pointer, you'd have to free that too. > wouldn’t it be better just to return NULL and guarantee that 0-sized allocations never use any memory at all? Better: takes less memory Worse: blinds you to this portability issue.
- Someone 1y ago> At the end of main, if the count wasn't balanced, then you knew you had a mismatch between malloc()/free(). A mismatch between malloc(0) and free(-1). You’d know nothing about calls to malloc with non-zero sizes.
- sgerenser 1y agoYeah, exactly, that’s my point. How many programs have memory leaks limited to (or even just materially affected by) 0-sized allocations? I’d have to imagine its a very small minority.
- bobmcnamara 1y agoThey're uncommon for sure. In the past they've been an issue for me on constrained systems where they can frag the heap as badly as any other long lived allocation.
- bobmcnamara 1y agoThose are identifiable by the end state of the heap not being empty.
- sweetjuly 1y agoDoes this work in practice? Now you have a bunch of invalid but non-NULL pointers flying around. NULL checks which would normally prevent you from accessing invalid pointers now will pass and send you along to deref your bogus pointer. Even hacking the compiler to treat -1 as equal to NULL as well wouldn't work since lots of software won't free NULL-like pointers.
- bobmcnamara 1y ago> NULL checks which would normally prevent you from accessing invalid pointers now will pass and send you along to deref your bogus pointer. Oddly, this is bog standard implementation specific behavior for standard C - caller accessing any result of malloc(0) is undefined behavior, and malloc(0) isn't required to return NULL - the reference heap didn't, and some probably still don't.
- sweetjuly 1y agoAh, that's my bad. Another day, another UB :)
- bobmcnamara 1y agoLike swimming in a bucket of rusty knives :)