The way that this is usually done is that you make your own header/source file and implement custom memory allocation functions.
A linked list works really well for keeping tabs on allocations, because you can free things in the middle of the list and then remove that element very easily.
Main file...
Code:
#include "GCMalloc.h"
...
banana = GCmalloc(numberOfElements * sizeof(*banana));
GCMalloc's implementation...
Code:
void *GCMalloc(size_t allocationSize)
{
// malloc allocation size
// if successful, add to list
// return result
}
void GCfree(void *elementToFree)
{
// free element and remove from list
}
void GCdispose(void)
{
// for each element in list, GCfree
}
void *GCCalloc(size_t nmemb, size_t size)
{
...
}
// To provide a consistant implementation, you will also need to have...
void *GCRealloc(void *ptr, size_t size);
{
...
}
That last one didn't use the list, but it is important that you create a consistant interface to work with.