Reputation: 408
I want to store pointers
that have been allocated using malloc()
in an array
and then free
all of them after. However even though the program doesn't complain it doesn't work. Below cleanMemManager()
won't actually free
the memory as when tested inside main()
the char* pointer
is not NULL
and it will print ???
.
code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void **ptrList = NULL;
void tfree(void** ptr)
{
free(*ptr);
*ptr = NULL;
}
void* talloc(int size)
{
void* ptr = malloc(size);
ptrList[0] = ptr; ///No clue if this actually does what I think it does
return ptrList[0];
}
void initMemManager()
{
ptrList = (void**)malloc(sizeof(void**) * 3);
memset(ptrList, 0, sizeof(void**) * 3);
}
void cleanMemManager()
{
tfree(&ptrList[0]); //Doesn't free the right pointer it seems
}
int main()
{
initMemManager();
char* ptr = (char*)talloc(3);
cleanMemManager();
if (ptr != NULL) //This will trigger and I'm not expecting it to
printf("???");
getchar();
return 0;
}
I don't understand the syntax to use for this, does the pointer not actually get touched at all? What is it freeing then since it doesn't throw any errors?
Upvotes: 2
Views: 1318
Reputation: 222763
In main
, char *ptr = (char*)talloc(3);
declares ptr
to be a local variable. It contains a copy of the value returned by talloc
, and none of your subroutines know about ptr
or where it is. So none of them change the value of ptr
. Thus, when you reach if (ptr != NULL)
, the value of ptr
has not changed.
Additionally:
In initMemManager
, you should use sizeof(void *)
in two places where you have sizeof(void**)
. In these places, you are allocating and copying void *
objects, not void **
objects.
It looks like you are trying to implement a sort of smart memory manager that automatically sets pointers to NULL
when they are freed. To do that in C, you would have to give up having copies of pointers. For example, ptr
is a copy of ptrList[0]
, but tfree
only sets whichever copy it is passed to NULL
. We could give advice on building such a system, but it would quickly become cumbersome—your memory manager needs to keep a database of pointers and their copies (and pointers derived from them, as by doing array arithmetic). Or you have to refer to everything indirectly through that ptrList
array, which adds some mess to your source code. Unfortunately, C is not a good language for this.
Upvotes: 5
Reputation: 952
Freeing doesn't guarantee that pointers pointing to the allocated block will be set to NULL. If you actually try doing
if (ptrList[0] != NULL)
printf("ptrList[0] != NULL");
you will see that the program won't output and if you remove the cleanMemManager()
function call, it will output. This means tfree
function is working as intended, it's freeing the memory that was allocated.
Now as to why ptr
variable being not set to NULL, it's simply because ptr
is still storing the old address. cleanMemManager()
has no way of mutating the variable ptr
. This is commonly called dangling pointer or use after free.
Also free()
doesn't clean/zero out the the allocated space, the block is simply marked as "free". The data will most likely remain in the memory for a moment until the free block is overwritten by another malloc
request.
Upvotes: 3