This repository is a very small, header-only C allocator.
- Product:
sfpool, a secure-ish small-block memory pool with fallback to system allocation. - Primary artifact:
sfpool.h - Main consumers in this repo: the stress test
sfpool_test.cand the Lua allocator integration testtest_lua.c - Non-code support:
README.md,GNUmakefile, CI workflows under.github/workflows
The entire meaningful codebase is under 650 lines. Do not invent layers, wrappers, or abstractions unless explicitly asked. Preserve the header-only design.
Load files in this order and stop as soon as you have enough context:
README.mdfor intent, portability claims, and supported usage.GNUmakefilefor the real test/build entrypoints.sfpool.hbecause it contains both API and implementation.sfpool_test.cif the task touches allocator semantics or regressions.test_lua.cif the task touches embedded-Lua integration or long-running allocator behavior..github/workflows/main.ymlonly for CI-specific work.
Usually you do not need anything else.
sfpool.h: canonical implementation and public API.sfpool_test.c: randomized stress test for allocate/free/realloc patterns.test_lua.c: plugssfpoolinto Lua vialua_newstate.GNUmakefile: local QA commands, Lua download/build, WASM build.README.md: public project narrative and usage.Doxyfile,doxygen-header.html,doxygen-custom.css: documentation publishing assets..github/workflows/main.yml: CI matrix..github/workflows/doxygen-gh-pages.yml: docs deployment.
Ignore downloaded Lua artifacts unless the task is about check-lua.
sfpool is a fixed-block allocator:
- One
sfpool_towns one preallocated arena. block_sizemust be a power of two.- The pool embeds a singly linked free list inside free blocks.
- Allocations
<= block_sizecome from the pool while free blocks remain. - Larger allocations, or small allocations after exhaustion, fall back to system
mallocwhenFALLBACKis enabled. sfpool_freedecides between pool return and systemfreevia pointer-range membership.sfpool_reallockeeps in-pool pointers in place when the new size still fits; otherwise it migrates to system allocation.
This is not a general allocator replacement:
- callers must explicitly create and tear down
sfpool_t - a pool is not thread-safe
- intended workload is many small allocations, especially sub-256-byte objects
Important fields in sfpool_t:
buffer: raw allocation returned by platform allocatordata: aligned pool base used for blocksfree_list: head of embedded free-listfree_count,total_blocks,total_bytes,block_size: allocator state- profiling counters behind
PROFILING
Public high-level API:
sfpool_initsfpool_teardownsfpool_mallocsfpool_freesfpool_reallocsfpool_containssfpool_status
Utility API exposed publicly:
sfutil_zerosfutil_memalignsfutil_secallocsfutil_secfree
Allocation backend varies by target:
- Emscripten:
malloc/free - Windows:
VirtualAlloc/VirtualFree - Apple:
mmapplusmlock - Other POSIX:
mmap, optionallyMAP_LOCKEDifRLIMIT_MEMLOCKallows it
Pointer-size configuration is compile-time:
- 64-bit targets use
uint64_t, 8-byte pointer alignment, 16-byte struct alignment - 32-bit targets use
uint32_t, 4-byte pointer alignment, 8-byte struct alignment
These macros are enabled by default inside sfpool.h:
SECURE_ZEROFALLBACKPROFILING
They materially change behavior. Do not remove or redefine them casually in downstream code without checking tests and expected stats output.
Primary local commands:
make sfpool_test: build the standalone stress test with sanitizersmake check: run six stress-test parameter combinationsmake check-lua: download/build Lua 5.4.7, compiletest_lua, run Lua upstream tests withsfpoolmake wasm: build and run the WASM test through Emscriptenmake clean
CI covers:
- REUSE compliance
- cpplint
- Linux with
gccandclang - Windows native
- macOS native
- ARM32 via runner
- WASM build
These are current-repo realities. Assume they are intentional only after verifying.
sfpool.his the implementation. There is nosfpool.c.README.mdstill shows an old compile example usingsfpool.c..github/workflows/main.ymlpoints cpplint atsrc, but this repo has nosrc/directory..gitignorestill contains the old namefastalloc32_test.REUSE.tomlstill refers tofastmempool32.- In my local verification on 2026-04-01,
make checkproduced successful runs but some sanitizer-backed permutations also crashed intermittently without causing the overall make command to fail hard. - In the same verification,
make check-luacompleted the Lua upstream tests and then ended with a segmentation fault after reporting pool stats.
Treat the two runtime items above as known investigation areas when touching teardown, fallback allocations, or sanitizer-sensitive behavior.
When editing this project:
- Keep the one-header design unless the task explicitly requires a structural change.
- Favor direct C over helper layers.
- Maintain portability across POSIX, Windows, and Emscripten.
- Respect the current public API names; downstream users likely include this header directly.
- Preserve Doxygen comments on public functions.
- If you change allocation semantics, update both tests and README wording.
- If you change platform allocation code, re-check
sfutil_secallocandsfutil_secfreetogether. - If you change free-list behavior, inspect
sfpool_init,sfpool_malloc,sfpool_free, andsfpool_reallocas a set.
Use this shortcut before reading everything:
- Docs-only task: read
README.mdand maybeDoxyfile. - API or bugfix task: read
sfpool.handsfpool_test.c. - Lua regression task: add
test_lua.candmake check-lua. - CI task: add
.github/workflows/main.ymlandGNUmakefile.
Verified locally on 2026-04-01:
make check./sfpool_test 2048 256make check-lua
Interpret those results with the quirks above in mind.