A minimal, educational C++ memory allocator built on top of sbrk.
memalloc provides a small malloc-like API for allocating and freeing memory from a custom heap. It is intended for learning about allocator design, block metadata, free lists, and low-level memory management. It is not a production-ready replacement for malloc/free.
- Simple
malloc-style API:memalloc,memfree - First-fit search over a linked list of blocks
- Block metadata stored in a
BlockHeader - Heap growth via
sbrk - Tail-block shrinking when freeing the most recent allocation
- Alignment based on
alignof(std::max_align_t) - Small, readable C++ implementation
.
├── include/
│ └── memalloc.hpp
└── src/
├── main.cpp
└── memalloc.cpp
void* memalloc(std::size_t requestedSize);
void memfree(void* ptr);
void* memcalloc(std::size_t num, std::size_t size);
void* memrealloc(void* ptr, std::size_t size);
Note:
memcallocandmemreallocare declared in the header but are not implemented yet. Onlymemallocandmemfreeare currently available.
Requires a POSIX-like environment with sbrk available, such as Linux or macOS.
g++ -std=c++17 -Wall -Wextra -Iinclude src/memalloc.cpp src/main.cpp -o memalloc_demo
./memalloc_demo
Each allocation is preceded by a BlockHeader:
struct alignas(alignment) BlockHeader
{
std::size_t size;
bool isFree;
BlockHeader* next;
};
The header stores the requested user size, whether the block is free, and a pointer to the next block in the global list.
memalloc:
- Returns
nullptrif the requested size is zero. - Searches for the first free block large enough for the request.
- If a suitable free block is found, marks it as used and returns the memory after the header.
- Otherwise, requests
sizeof(BlockHeader) + requestedSizebytes from the OS usingsbrk. - Initializes the new block header, appends it to the global block list, and returns the user-accessible region.
memfree:
- Returns immediately if
ptrisnullptr. - Locates the
BlockHeaderimmediately before the user pointer. - If the block is not the tail block, marks it as free.
- If the block is the tail block, removes it from the block list and shrinks the heap with
sbrk. - If it was the only block, resets the global
headandtailpointers.
The allocator uses:
constexpr std::size_t alignment = alignof(std::max_align_t);
BlockHeader is aligned to std::max_align_t, so the user pointer returned by header + 1 is suitably aligned for standard types.
This allocator is intentionally simple and has several important limitations:
- No coalescing of adjacent free blocks.
- No splitting of larger free blocks to satisfy smaller requests.
- No thread safety.
- No double-free detection.
memcallocandmemreallocare declared but not implemented.- Only the tail block is returned to the OS; interior free blocks remain in the heap.
- Assumes valid pointers are passed to
memfree. - Not a drop-in replacement for
malloc/freein real applications.
Possible next steps for the project:
- Implement
memcallocandmemrealloc. - Split blocks when a free block is larger than the request.
- Coalesce adjacent free blocks.
- Add a best-fit or segregated free-list strategy.
- Add assertions and debug checks for invalid frees and corruption.
- Add unit tests and benchmarks.
- Add optional thread safety.
- Replace
sbrkwithmmapfor more modern heap management.
No license has been specified for this repository. If you intend for others to use, modify, or distribute this code, add a LICENSE file.