Game Development Reference
In-Depth Information
pHeader->pStart = reinterpret_cast<char*>(pHeader)+SIZE_OF_MEMORY_HEADER;
pHeader->pNextFree = reinterpret_cast<char*>(pHeader->pStart) + size;
pHeader->size = size;
return pHeader->pStart;
}
The
new
operator is passed the
size
of the allocation we would like to reserve and returns a
void*
to the beginning of the block of memory to which the user can write. The function begins by looping
over the existing memory allocations until it finds the first allocated block with a
nullptr
in the
pNextFree
variable.
Once it finds a free block of memory, the
pStart
pointer is initialized to be the address of the free
block plus the size of the memory allocation header. This ensures that every allocation also includes
space for the
pStart
and
pNextFree
pointer and the
size
of the allocation. The new function ends by
returning the value stored in
pHeader->pStart
ensuring that the user doesn't know anything about
the
MemoryAllocationHeader struct
. They simply receive a pointer to a block of memory of the
size
they requested.
Once we have allocated memory, we can also free that memory. The overloaded
delete
operator
clears the allocations from our heap in Listing 22-8.
Listing 22-8. The Overloaded
delete
Function
void operator delete(void* pMemory)
{
MemoryAllocationHeader* pLast = nullptr;
MemoryAllocationHeader* pCurrent =
reinterpret_cast<MemoryAllocationHeader*>(pMemoryHeap);
while (pCurrent != nullptr && pCurrent->pStart != pMemory)
{
pLast = pCurrent;
pCurrent = reinterpret_cast<MemoryAllocationHeader*>(pCurrent->pNextFree);
}
if (pLast != nullptr)
{
pLast->pNextFree = reinterpret_cast<char*>(pCurrent->pNextFree);
}
pCurrent->pStart = nullptr;
pCurrent->pNextFree = nullptr;
pCurrent->size = 0;
}
This operator traverses the heap using two pointers,
pLast
and
pCurrent
. The heap is traversed until
the pointer passed in
pMemory
is matched against an allocated memory block stored in the
pStart
pointer in a
MemoryAllocationHeader struct
. Once we find the matching allocation we set the
pNextFree
pointer to the address stored in
pCurrent->pNextFree
. This is the point at which we create
two problems. We have fragmented our memory by freeing memory potentially between two other
blocks of allocated memory, meaning that only an allocation of the same size or smaller can be filled