0

I am going through the CS50 course, and this last part of code was written by the instructor to free the memory used :

ptr = list;
while (ptr != NULL)
{
    node *next = ptr->next;
    free(ptr);
    ptr = next;
}

I understand the need to use next as a temporary pointer, but why is "ptr" (a temporary point for the original pointer to the start of the linked list "list" used to free the memory? Is there any reason for not using "list" directly?

while (list != NULL)
{
    node *next = list->next; 
    free(list);
    list = next;
}

I tried doing this instead, and it seems to work the same; are there any concerns about freeing list directly?

Celes
  • 3
  • 2
  • 3
    Note that in the second example, `ptr` does not change in the body of the loop, thus the loop will either never run or run forever. If this was intended to be `while (list != NULL)`, then you should [edit] your question. A more complete (able to be compiled and executed) [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) would also be welcomed. – Oka Jul 11 '23 at 03:04
  • Thanks for the reminder! I just got into coding for a few days, the edit has been made :))) – Celes Jul 11 '23 at 09:34

2 Answers2

1

At around 1:22:00 (one hour and twenty-two minutes) in CS50x 2023 - Lecture 5 - Data Structures, this code is shown.

The temporary ptr exists simply because the lecturer uses it to first print the contents of the list, without losing track of the root node (list itself).

node *ptr = list;
while (ptr != NULL)
{   
    printf("%i\n", ptr->number);
    ptr = ptr->next;
}

After this loop, ptr is NULL.

ptr is then reused (again set to list beforehand) for the loop that frees all the nodes, as seen in your first snippet.

This is purely a style choice - you could just as well use just list if you do not care to retain the value it holds (useless after free). In fact, in a previous year's lecture (~ 1:07:00 in CS50 2021 in HDR - Lecture 5 - Data Structures), the code

while (list != NULL)
{   
    node *tmp = list->next;
    free(list);
    list = tmp;
}

is used, which does just that.

Oka
  • 23,367
  • 6
  • 42
  • 53
-1

tl;dr yes, you can use list directly, as long as while (list != NULL)

Memory leak

Yes, these two are very different. The second implementation causes a memory leak.

Memory leak is a very common bug in low level languages like c, exactly because your program "seems to work the same." In fact, you can simply do list = NULL and the program will still work (albeit not properly). However, without calling free, the memory occupied. In addition, you have lost track of the pointer, so it's impossible to free the memory later. This is a memory leak. If it's just a small leak, nothing bad will happen. In a large program, it will eat up your computer's RAM. You can try this by calling malloc a bunch of times and checking the program's memory usage.

Also check out What REALLY happens when you don't free after malloc before program termination?

Your code

If you mean while (list != NULL) instead of while (ptr != null) then I'm pretty sure your code is correct, and you can use list directly without ptr (I only realized you might've made a typo after typing all the previous explanation ). The instructors might have chosen to use an extra ptr variable for consistency with how they traverse the linked list in other functions.

But with what you have now, the code is equivalent to a single line of free(list);. None of the elements except the first will be freed.

P.S. you can check for memory leak with gcc -fsanitize=address program.c (does not work with mingw).

EJam
  • 164
  • 5
  • Hi EJam, thanks for helping out! But doesn't a single line of free(list) only free the number in the first node instead of freeing all the numbers in every node? – Celes Jul 11 '23 at 09:51
  • @Celes Yes, so it does not work. I wrote this answer before you edited your question – EJam Jul 11 '23 at 12:18
  • 1
    I see! Was confused there, thanks a lot! – Celes Jul 11 '23 at 14:29