I'll simplify this as much as I can and do my best explaining it.
You have 1000 bytes of heap memory. The bytes are numbered from 1 to 1000 (byte addresses).
You need 2 variables:
heap_bottom = 1 // This marks the start of unused heap memory.. when this reaches 1000 then all the memory is used. Possible free memory is in the freelist.
freelist_pointer = NULL // this is a pointer to first free memoryblock.. initially NULL
When you want to allocate 10 bytes of memory you record that size in the byte just before the actual memory pointer that is returned. So after calling malloc(10) the variables contain:
heap_bottom == 12
freelist_pointer == NULL
Malloc returned pointer to memory location 2 and location 1 contains the value 10.
After calling malloc(20)
heap_bottom == 33
freelist_pointer == NULL
Malloc returned pointer to memory location 13 and location 12 contains the value 20
After calling malloc(10)
heap_bottom == 44
freelist_pointer == NULL
Malloc returned pointer to memory location 34 and location 33 contains the value 10
Now.. lets free memory, call to free(2) should free the memory at that position. All we need to do is to write that pointer value to the freelist.
freelist_pointer == 2
We also write NULL to the memory location 2, because this memory block is the last node of our list.
Free(34):
Now, we need to link this memory bloc to the freelist. This is simple linked list addition.
Write 34 to the last nodes pointer and set this node as last node.
memory location 2 == 34
memory location 34 == NULL
Now, our variable "freelist_pointer" pointer points to memory location 2, which in turn points to memory location 34, which points to NULL.
When you need to know the size of the free memory block, you just read the byte before the memory block i.e. locations 1 and 33 in this case.
Well.. that is quite a mess. One good picture would explain it much better. These pictures are not exactly related to my text. But very close.