Previous post discussed pointer
arithmetic and common elements that goes with any generic container. This post
would look in to the memory management part and add another common element to
the struct of the generic container.
Primary functions that are being
used for dynamic memory management are malloc, realloc and free functions.
Malloc – void *malloc(size_t
number) takes the number of bytes that needs to be allocated as the input
parameter and return the starting address of the allocated block in heap.
Realloc – void *realloc(void*
ptr, size_t size) takes a pointer returned by malloc and the required new size
and returns the address of the block. Realloc is basically for resizing a block
allocated by malloc function. This function extends the size if there is enough
contiguous memory starting from the input pointer, if contiguous memory block
starting at the input pointer is not available it would relocate the block to a
new place and copy the content in the old block and return the starting address
of the new block.
Free – void *free(void *ptr) free
the memory and donate it back to the heap. We must free up the memory after we
are done using it so that enough space is available for new memory requests.
So, when someone initialize our
container we should allocate memory using malloc, if our container allows
resizing like a Vector we should use realloc for resizing rather than malloc
and copy and free sequence by ourselves and finally we should free the memory
used by our stack when user want to dispose the container.
Its quite simple. But think of
the disposal. If the data type stored in our container is something like int or
double they would get vanish when we clear the memory block of our container.
But if the data type is a pointer to some struct on the heap, we would only
lose the references that were stored in our container and the memory for the
struct will not be donated back to the heap. Therefore we need a way to clear
them, but unfortunately we don’t know how so the user have to tell us how by
giving us a function which would free the memory and we would use that function
to free up memory at the disposal of our container.
So, we got a new element to the
common list of things that a container struct need to maintain, that is a
pointer to a function to free up the memory. If the container holds built in
types such as int and float user could pass in NULL and we don’t have to worry
about it.
When an item is inserted to the
container I assumed that the ownership is given to us that is the reason that we
had to worry about cleaning the things that were still there in the container
at the disposal. The ownership also implies that we need to copy whatever the
element inserted to the container using memcpy so that it is available throughout
the lifetime of the container.
So now we have the common
elements and pointer arithmetic knowledge. It is time for an example. First the
simple generic stack, then the generic vector which also introduce the memmove
function.
Note: This is an old post moved here from a different location.