Just for fun (and for C programming practice) I wrote the following piece of code that does the following:
- Acts as a tracking system for memory allocations
- Frees all dynamically allocated memory with a function call
Here is the code:
typedef enum _OpMode {
OM_APPEND,
OM_DESTROY
} OP_MODE;
void refOp(void *ptr, OP_MODE mode) {
/* contains static array of pointers and provides an interface to that
array */
static void **references = NULL;
static int size = 0;
static int reset = 0;
if (reset) {
reset = 0;
references = NULL;
size = 0;
}
switch (mode) {
case OM_APPEND:
//add a pointer to reference array
references = (void**) realloc(references, sizeof(void*) * (size + 1));
references[size++] = ptr;
break;
case OM_DESTROY:
//free memory at all pointers kept in reference array
for (int i = 0; i < size; i++) {
free(references[i]);
references[i] = NULL;
}
free(references);
reset = 1;
break;
default:
printf("Invalid enum value '%d' passed as mode.\n", mode);
break;
}
}
void refDestroyAll() {
//Wrapper function
refOp(NULL, OM_DESTROY);
}
void *myAlloc(void* ptr, size_t size) {
/* Allocates memory and stores pointer copy in reference array */
void *tmp_ptr;
tmp_ptr = realloc(ptr, size);
refOp(tmp_ptr, OM_APPEND);
return tmp_ptr;
}
The idea is that one would use myAlloc() instead of malloc or realloc to dynamically allocate memory. And one would use refDestroyAll() to free all memory that was created with myAlloc().
I’ve done some testing, and it seems to be working, but I can’t help feeling that I’m missing something important. Does this code actually work as intended, or am I leaking memory when I call refDestroyAll()?
You have a bug, that could cause a segmentation fault.
realloc()could return the same pointer as it is given, in which case you would have added it twice to the array. When you call your free function, it would try and free the same pointer twice, resulting in a segmentation fault error.Additionally, I don’t understand why you have the reset parameter. Why not simply set references and size to 0 in the
OM_DESTROYcase? It is good practice to always set a pointer to NULL immediately after freeing it.