GlobalAlloc::alloc()
has a (surprising to some) safety precondition that the layout must have non-zero size. This means that writing code polymorphic over the layout size requires branching on whether the layout size is zero before allocating with that layout. If this required branching is forgotten, the code has undefined behavior for layouts with zero size.
In a world where GlobalAlloc::alloc()
would be defined on zero size layouts to return a dangling pointer (non-zero, well-aligned), generic code could simply be parametric over the layout size without branches. Some additional consequences would be:
- Less chances of undefined behaviors by simplifying a surprising safety precondition.
- Better code size by factorizing the zero-size branch inside the allocator (if the allocator needs at all such special logic) instead of having it in all polymorphic callers.
- Worse performance by forcing the allocator to handle zero-size layouts even when it is not called with such layouts (and assuming the allocator needs special logic to support zero-size layouts).
My questions to the forum:
- Is allocation (and thus deallocation) the only operation that is not parametric over the layout size? (AFAICT reading and writing zero bytes on a dangling pointer is well-defined.) If the answer is no, then the hypothetical change above would not be enough to achieve its goal.
- Are there other negative consequences to the hypothetical change above (besides worse performance and that it's a breaking change for allocators)?
- What was the rationale behind requiring non-zero size layouts? Was it not clear how to specify the behavior in such cases at the time?