3
STUDENT ** list=NULL;
char *getid;
getid =(char*)malloc(sizeof(char) * 8);
printf("How many student? ");
int menuNum,num=0;

scanf("%d",&num);
list=(STUDENT**)malloc(num*sizeof(STUDENT*));

I used pointer like this. As I learned from the professor, before finishing my code, I ought to use free() function to retrieve the allocated memory again.

Here s what i wanna ask you.

I learned that If i wanna use free() about (char *getid)

I know I should write

free(getid);

then How can I use free about

STUDENT ** list = NULL ; // **It's about struct**

Should I use like

free(list);

or

free(*list);

I think the former is right, but when I write like the latter, there's no error on my X-code.

Could you tell me about it ?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
CNotice
  • 33
  • 1
  • 4
  • 3
    `free(list);`. Each time you do `X = malloc(Y)`; you do `free(X)` later. – Jabberwocky Jun 09 '17 at 15:29
  • 1
    Basic priniciple: store result of malloc in a pointer variable, free that pointer. What is unclear? – Yunnosch Jun 09 '17 at 15:29
  • Should I write malloc and write free() immediately? not in the end of the line? – CNotice Jun 09 '17 at 15:34
  • 1
    Since you haven't allocated space for `list[i]` for any i, list is currently pointing to a bunch of uninitialized pointers. you will need to to `list[i] = malloc ( ....` before you can use any of them. Then, when you are done, you will do `free(list[i])` for all i and then `free(list)` – William Pursell Jun 09 '17 at 15:34
  • 2
    @CNotice _Should I write malloc and write free() immediately? not in the end of the line?_ could you clarify? You call free when you want to free the memory, and only then. – Jabberwocky Jun 09 '17 at 15:42

2 Answers2

4

You should use:

free(list);

but when I write like free(*list);, there's no error on my X-code

That's why *list does not deallocate anything, since nothing is allocated there. However, your program suffers from a memory leak that way, since the memory pointed to by the double pointer named list is not free'd. However, you are just (un)lucky not to see your program crash.

If you used Valgrind though, you would see the memory leak.

Should I write malloc and write free() immediately? not in the end of the line?

No. You first allocate the memory dynamically with malloc(), then you use this memory (initialize, access, etc.) and when you do not need the memory anymore, and only then, you deallocate it with free().


However, if you had dynamically allocated space for list[i], then you should do:

free(list[i]);
free(list);

where the order matters, since you do not want to have tangling pointers!

Maybe my example on dynamically allocated a 2D array will more explanatory on this, even though it's a different data structure than a list.


PS: We don't cast what malloc returns.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
3

You should free any memory allocated by malloc with free...

as you figured out, you requested 8 bytes of memory and saved the Pointer to it to your symbol getid (getid =(char*)malloc(sizeof(char) * 8);)

as for your list, this is a bit trickier:
You actually allocating a list of pointers that should point to other memory locations (those might be dynamically allocated as well)

list=(STUDENT**)malloc(num*sizeof(STUDENT*)); size of num pointers
Allocates the space for the list and saves the pointer to it at symbol list.

I'd remind that the memory allocated doesn't have to come initialized from the OS, so we should initialize it.

for(int i=0; i<num; i++)
{
   list[i] = NULL;
}       

You could also use memset(list, NULL, num * sizeof(STUDENT*)).

and you are very much correct you should free its memory by free(list),
But you should free the items in the list BEFORE you free the list of pointers itself. (again, if the items were dynamically allocated!)

for(int i=0; i<num; i++)
{
   if(list[i] != NULL) // only if allocated.
   {
      free(list[i]); // free the element @ position i
      list[i] = NULL;
   }
}
Tomer W
  • 3,395
  • 2
  • 29
  • 44
  • 1
    the `free()` function properly handles the case of being passed a NULL pointer, so no need to check if the `list[i]` is not NULL. – user3629249 Jun 10 '17 at 02:22
  • is it by definition? i m always wery that different Clibs will act differently. – Tomer W Jun 10 '17 at 05:46
  • you might want to read the `man` page for `free()`, which includes the statement: *If ptr is NULL, no operation is performed.* – user3629249 Jun 10 '17 at 14:34
  • @user3629249 then don i have to call all free(list[i])? – CNotice Jun 14 '17 at 04:18
  • @CNotice You Do! In my answer, before i call `free(list[i])` i check for nulls, in order to prevent from deallocating invalid memory pointer. t @user3629249 pointed out that the method `free(void*)` is doing the check already, so my `if(list[i]==NULL)` is redundant. – Tomer W Jun 14 '17 at 06:08
  • Then as a result, Should I write like this? Free(list[I])and Free(list)? – CNotice Jun 14 '17 at 09:34
  • I used this list[i]->a .... like this So i should free(list[i]) , and hen free(list) ? Right? – CNotice Jun 14 '17 at 09:48