Writing a simple pool allocator in C
Allocator design & implementation choices
- Several commenters note that fixed-size pool allocators are common (e.g., in RTOSes, embedded code, and personal libraries).
- Questions arise about why the
Poolstruct (just a couple of pointers) is heap-allocated at all, and why two separatemalloc()calls are used instead of co-allocating control structure and chunks. - Some argue co-allocation reduces fragmentation and improves performance; others say it complicates an educational example, especially if targeting C89 without flexible array members.
- Alignment is a recurring concern: aligning chunk sizes, ensuring space for an internal pointer in free-list nodes, and potentially using C11 features like
_Alignas(max_align_t).
Free-list structure & performance
- One participant criticizes linked lists for allocator bookkeeping, favoring trees or bitsets for cache locality and asymptotic complexity.
- Others respond that this particular pool allocator never searches; it only pushes/pops from the head, so operations are O(1), making a simple singly linked free list appropriate.
- Distinction is made between “free list” as an old term of art and the more precise idea that this usage is effectively a stack.
Safety, tooling, and debugging
- Suggestions include adding: thread safety, variable-sized allocations, automatic zeroing, double-free detection, and better error checking.
- Multiple comments recommend integrating with Valgrind and AddressSanitizer via their APIs (including manual poisoning/redzones) so that custom allocators still benefit from modern debugging tools.
- Some embedded and GC examples are mentioned where cooperating with these tools avoids false positives.
Strict aliasing, C object model, and UB
- A long subthread debates whether such allocators violate C’s strict-aliasing and effective-type rules.
- Views range from “allocators inevitably break the model, so the model is broken” to “type-changing stores into allocated storage are explicitly allowed in C, if done carefully.”
- There is disagreement over whether
malloc()itself can be written in strictly conforming C, touching on pointer provenance, out-of-bounds pointers, and hardware features like memory tagging. - Some projects simply disable strict aliasing (
-fno-strict-aliasing) in practice.
API design & ergonomics
- Several commenters propose:
- Making chunk size a per-pool parameter (one pool per object type).
- Hiding
pool_expand()and number-of-chunks; auto-expand insidepool_alloc(). - Lazy initialization on first allocation instead of allocating in
pool_new(). - Treating the pool like a stack with an operation to free everything back to a saved “index”.
Benchmarking & real-world use
- The article’s claim that pools are “much faster than malloc” is challenged; commenters insist on concrete benchmarks and realistic workloads.
- Detailed advice is shared on how to design, run, and interpret allocator benchmarks, including controlling environment, varying workloads, and using profiling tools.
- It’s noted that specialized allocators can win big for specific load profiles, but the system allocator comes with built-in debugging and security checks that custom allocators risk losing.