These musings will be obvious to some, but these are some things that took some time for me to pick up, and so I hope some others will find this useful.
The DebugAllocator is not a singleton. It is often declared at the entry point to a program and deinitialized at program exit, but you’re free to declare many DebugAllocator instances. This may be useful if you want early feedback on leaked memory before terminating the program. This is particularly useful in similar cases as the ArenaAllocator here you have some cyclical allocation pattern, and you want to be able to track leaks within the cycle.
For example, I have been writing a network service, and I have allocations that I want to tie to the lifetime of my client connections. Instead of waiting for my service to terminate to see if there were any leaks when processing the client connection, I create a new DebugAllocator for every client, and I use that for the allocations for that client, and I deinitialize that allocator when the client connection closes. This early feedback is much more convenient than killing the service every time you want to see the leak feedback.
Another interesting thing about the DebugAllocator is able to wrap arbitrary std.mem.Allocators. By default it wraps the singleton std.heap.page_allocator. Off the top of my head, some ways I can see this be particularly useful is to wrap FixedBufferAllocator or ArenaAllocator when you want to make sure that the code you are passing these allocators to would behave correctly if someone were to pass an allocator that expects individual frees.