Surprising behaviour of std.experimental.allocator

ag0aep6g anonymous at example.com
Sat Dec 26 19:36:24 UTC 2020


On 26.12.20 13:59, ag0aep6g wrote:
> Looks like a pretty nasty bug somewhere in std.experimental.allocator or 
> (less likely) the GC. Further reduced code:
> 
> ----
[...]
> ----
> 
> Apparently, something calls deallocateAll on a Mallocator instance after 
> the memory of that instance has been recycled by the GC. Maybe 
> allocatorObject or AllocatorList keep a reference to GC memory out of 
> sight of the GC.

I've looked into it some more, and as far as I can tell this is what 
happens:

1) allocatorObject puts the AllocatorList instance into malloced memory.
2) The AllocatorList puts the Mallocator instance into GC memory, 
because its default BookkeepingAllocator is GCAllocator.
3) The GC recycles the memory of the Mallocator instance, because it's 
only reachable via the malloced AllocatorList instance and malloced 
memory isn't scanned by default.
4) Hell breaks loose because that recycled memory was not actually garbage.

I'm not so sure anymore if this qualifies as a bug in 
std.experimental.allocator. Maybe AllocatorList should be registering 
its GC allocations as roots?

As a solution/workaround, you can use NullAllocator for AllocatorList's 
BookkeepingAllocator:

----
import std.experimental.allocator.building_blocks.null_allocator :
     NullAllocator;
alias Alloc1 = FallbackAllocator!(
     AllocatorList!(n => Region!Mallocator(1024*1024), NullAllocator),
     Mallocator);
----


More information about the Digitalmars-d-learn mailing list