So in general, there must be a free list of the memory blocks not in use and available for allocation.
This list needs to keep track of the beginning address of each free memory block and the size of the block.
Memory allocation will select a free memory block (or part of one) which is big enough for the memory request and remove the block (or part of it) from the free list.
Process termination requires returning the memory to the free list.