Plain header only implementation of malloc/free over a fixed buffer.
#include "mameMalloc.h"
static uint8_t pool[ 8192 ];
mameMalloc_initialize( pool, sizeof pool, 3 ); /* 1 << 3 == 8 byte blocks */
void* p = malloc( 100 );
free( p );
mameMalloc_finalize();malloc, free, calloc and realloc are thin wrappers over
mameMalloc_alloc and mameMalloc_free. All four are replaced together on
purpose: replacing only malloc and free leaves calloc served by the C
library while its pointers reach this free, which crashes. Defining MAME_MALLOC_DISABLE_STD_INTERFACE leaves the
global malloc alone and exposes only the prefixed pair, which is what the
sanitised test build uses — AddressSanitizer replaces malloc itself and
cannot share it.
Outside the window between mameMalloc_initialize and mameMalloc_finalize,
mameMalloc_alloc returns NULL and mameMalloc_free does nothing. It has to:
with the wrapper on, library constructors reach malloc before main and
teardown code reaches free after mameMalloc_finalize, and asserting there
cannot work because assert formats its message through malloc and free.
- The definitions are neither
staticnorinline; including the header from more than one translation unit fails to link. - A single global pool. There is no way to create a second one.
- Returned pointers are aligned to the block size, which
mameMalloc_initializerequires to be at leastsizeof(void*). That is notmax_align_t, so an over-aligned type still needs a wider block. - Not thread safe and not reentrant, so it is not safe to call from an interrupt handler.
- Every allocation costs
sizeof(mameMalloc_header)on top of the payload, rounded up to the block size.
make test # both suites
make main # the original smoke testtest_mameMalloc.c drives the core allocator under ASan and UBSan. Each pool is
mapped with a PROT_NONE page flush against its last byte and another before
it, so anything that leaves the pool faults immediately — the sanitizers cannot
see inside an mmap the allocator carves up by hand.
test_mameMalloc_std.c covers the malloc/free wrapper. It replaces the
global allocator, so it builds without sanitizers and relies on the guard pages.
MIT. See LICENSE.