Compaction attacks the problem of fragmentation by moving all the allocated blocks to one end of memory, thus combining all the holes. Unless it is possible to find all such pointers, compaction is not possible. Pointers can stored in the allocated blocks themselves as well as other places in the client of the memory manager. In some situations, pointers can point not only to the start of blocks but also into their bodies. For example, if a block contains executable code, a branch instruction might be a pointer to another location in the same block.
Compaction is performed in three phases.
First, the new location of each block is calculated to determine the distance the block will be moved. Finally, the data is actually moved. There are various clever tricks possible to combine these operations. Garbage collection finds blocks of memory that are inaccessible and returns them to the free list. The conservative approach may fail to collect blocks that are garbage, but it will never mistakenly collect accessible blocks.