A Malloc Tutorial
Malloc allocates memory in C:
- It takes a parameter,
size
, and this must be at least the number of bytes requested. - The pointer returned points to the space.
- No other call to malloc can allocate memory within this space while it is in use and has not been freed.
- the pointer should be able to be resized and freed.
void* malloc(size_t size);
The Heap, brk
and sbrk
The heap (free memory) of a process has a start, and a break
, which is where the mapped region of memory ends. Afterwards, there is the unmapped region, which ends with rlimit
, which is not in use.
We can use two system calls to help out with this:
int brk(const void *addr);
void* sbrk (intptr_t incr);
brk
sets the break value to addr
, and changes allocated space. sbrk
takes in incr
as a parameter, and either increments or decrements the process break by that amount.
sbrk(0)
returns the current program break.
mmap
and munmap
can be used to free memory as well.
Dummy Malloc
The first malloc is a bump allocator. When we get a call for some amount of memory, we bump the space by that many bytes. We cannot realloc or free, so this is a big downside, but it is as fast as possible.
void *malloc(size_t size) {
void *p = sbrk(0); // get program break
if (sbrk(size) == -1) { return NULL; } // alloc failed
return p; // return the start of the allocation
}
Organizing the Heap
To be able to reallocate and free, we need bookkeeping information. Let’s keep metadata before the data, such as the pointer, length, and then the next free block (a free list).
struct s_block {
size_t size; // size of allocation
struct s_block* next; // next free block
bool free; // bool for free/not
}
A First Fit Malloc
This implementation is of a malloc that traverses the chunk list and when a suitable free block is found, we use that.
We just make sure to align to the pointer size, and then find a chunk:
If we find no suitable blocks, we use sbrk to increment the heap.
If there’s a suitable block that’s too big, we can also split the block into two.