I am new in C, trying to figure out about memory allocation in C that I kinda confused
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
} struct1_t;
int main()
{
funct1(); //init pointer
return 1;
}
int funct2(struct1_t *ptr2struct)
{
printf("print a is %d\n",ptr2struct->a);
//free(ptr2struct);
printf("value of ptr in funct2 is %p\n", ptr2struct);
return 1; //success
}
int funct1(){
struct1_t *ptr2struct = NULL;
ptr2struct = malloc(sizeof(*ptr2struct));
ptr2struct->a = 5;
printf("value of ptr before used is %p", ptr2struct);
if (funct2(ptr2struct) == 0) {
goto error;
}
free(ptr2struct);
printf("value of ptr in funct1 after freed is is %p\n", ptr2struct);
return 1;
error:
if(ptr2struct) free(ptr2struct);
return 0;
}
I have funct 1 that calls funct 2, and after using the allocated pointer in funct1, I try to free the pointer. And I create a case where if the return value in funct2 is not 1, then try again to free the pointer.
My question is below
which practice is better, if I should free the memory in funct2 (after I pass it) or in funct1 (after I finish getting the return value of funct1)
The second thing is whether this is correct to make a goto error, and error:
if(ptr2struct) free(ptr2struct);
My third question is , how do I check if the allocated value is already freed or not? because after getting the return value, I free the pointer, but if I print it, it shows the same location with the allocated one (so not a null pointer).
1) Should I free it in the calling function or in the called function?
I try to do the free-ing in the same function that does the malloc-ing. This keeps the memory-management concerns in one place and also gives better separation of concerns, since the called function in this case can also work with pointers that have not been malloc-ed or use the same pointer twice (if you want to do that).
2) Is it correct to do a “goto error”?
Yes! By jumping to a single place at the end of the function you avoid having to duplicate the resource-releasing code. This is a common pattern and isn’t that bad since the “goto” is just serving as a kind of “return” statement and isn’t doing any of its really tricky and evil stuff it is more known for.
C++, on the other hand, has a neat way to do this kind of resource management. Since destructors are deterministically called right before a function exits they can be used to neatly package this king of resource management. They call this technique RAII
Another way other languages have to deal with this is finally blocks.
3) Can I see if a pointer has already been freed?
Sadly, you can’t. What some people do is setting the pointer variable value to NULL after freeing it. It doesn’t hurt (since its old value shouldn’t be used after being freed anyway) and it has the nice property that freeing a null pointer is specified to be a no-op.
However, doing so is not foolproof. Be careful about having other variables aliasing the same pointer since they will still contain the old value, that is now a dangerous dangling pointer.