rust-lang / wg-allocators

Home of the Allocators working group: Paving a path for a standard set of allocator traits to be used in collections!
http://bit.ly/hello-wg-allocators
203 stars 9 forks source link

Behavior of zero-sized allocations is insufficiently specified #111

Open CAD97 opened 1 year ago

CAD97 commented 1 year ago

GlobalAlloc sidesteps the issue by making it the caller's problem and forbidding zero-sized allocations. Allocator makes it the job of the allocator to accept a zero-sized allocation request.

If either of these are true, we might end up where it's still considered good practice to not do an "actual" allocation for zero-sized allocations, and have a special case to use Layout::dangling in the caller instead. For the former, to avoid unnecessary allocation requirements/failures; for the latter, to avoid unnecessary allocation pressure.

The latter condition also carries an additional potential pitfall, in that deallocating a zero-sized allocation multiple times, or an allocation not made in this allocator, would be potential UB. This UB is unlikely to be caught with miri and the default global allocator; the current UCG leaning is to always allow all ZST accesses, irrespective of provenance, even after deallocation, and Global uses Layout::dangling to service zero-sized allocations (and does nothing for deallocation).

I personally think that we should just require zero-sized allocation requests to always succeed, and for zero-sized deallocation to be idempotent. However, if the ultimate decision of ucg#93 is that ZST accesses to deallocated provenance are invalid, then it might make sense to extend that flexibility to Allocator implementations to do actual work for zero-sized allocations (but still encourage zero-sized allocation to just be Layout::dangling/fake_alloc equivalent).

Either way, this should be spelled out more clearly in the documentation.

zakarumych commented 1 year ago

By reading documentation I can conclude that right now

Are Allocators allowed to fail to allocate zero-sized allocations?

Yes, since allocators are allowed to fail whenever they feel like it.

Are Allocators allowed to do a real memory block allocation for zero-sized allocations?

Yes and they can even return non-zero memory slice from allocate method.

Amanieu commented 1 year ago
  • Are Allocators allowed to fail to allocate zero-sized allocations?

  • Are Allocators allowed to do a real memory block allocation for zero-sized allocations?

Yes to both. The only requirement is that dealloc must accept an allocation returned by alloc.

If either of these are true, we might end up where it's still considered good practice to not do an "actual" allocation for zero-sized allocations, and have a special case to use Layout::dangling in the caller instead. For the former, to avoid unnecessary allocation requirements/failures; for the latter, to avoid unnecessary allocation pressure.

The rule of thumb is essentially:

For an example where this is relevant, consider a bump-pointer allocator such as bumpalo: it is faster to just bump the pointer by 0 bytes than to add a check for whether the layout is a ZST.