Welcome to the Builder Academy

Question free_followers() in db.c

More
08 May 2016 23:16 #5862 by krell
Hi, I have a question about free_followers in db.c so I can be sure I understand it.

Code:
static void free_followers(struct follow_type *k) { if (!k) return; if (k->next) free_followers(k->next); k->follower = NULL; free(k); }

The part of the function that I might need clarification on is the recursive section:
Code:
if (k->next) free_followers(k->next);

I think it's saying "If not the last pointer in the list then move to the next pointer, pass that as an argument to this existing function and test again."

Please correct me if I'm wrong or my understanding is incomplete because I want to make sure I've wrapped my head around this. Thanks.

Please Log in or Create an account to join the conversation.

More
09 May 2016 19:58 #5864 by thomas
Replied by thomas on topic free_followers() in db.c
Yes, the function recursively calls itself with the "next" follower, before free()'ing anything.

If we start out with this layout:
Code:
k -> follower | v next -> follower | v next -> follower | v NULL
Then the first check obviously is false (k is something). Then, this is passed to the function:
Code:
next -> follower | v next -> follower | v NULL
On this, second call to the function, the internal representation of state looks like this:
Code:
k -> follower | v next -> follower | v NULL
Again, the first check is false (again, k is something). So the function is called again, with "k->next" as argument.:
Code:
next -> follower | v NULL
Internally, this is seen as
Code:
k -> follower | v NULL
Again, k is something. So we call this function with k->next as the argument:
Code:
NULL
Now, on the fourth call, k is NULL. This means the recursion stops, and the function returns immediately.
So, we're back in the third call, where k still is something, and we're done with k->next. Now we null out the follower and free the struct.
The implicit return at the end of the function brings us to the second call.
Here we are right after the free_followers(k->next) call and have this data structure:
Code:
k -> follower | v free()'d memory
So we clean up by free()'ing the k object, and traversing up the call stack to the first call. This has exactly the same data structure:
Code:
k -> follower | v free()'d memory
(Albeit with a different memory address for the k and free'd memory). Again, we free k, and we're done with the last (and first) call to the function.

Please Log in or Create an account to join the conversation.

More
14 May 2016 05:12 #5881 by krell
Replied by krell on topic free_followers() in db.c
Thanks thomas form taking the time to deal with my question in-depth like that. So the function recursively finds all of the elements of the list and then removes them.

This leads me to another question about the function. Should k -> follower be free()'d then NULL'd and should k be NULL'd after being free()'d?

Please Log in or Create an account to join the conversation.

More
14 May 2016 13:51 #5882 by thomas
Replied by thomas on topic free_followers() in db.c
No, setting k = NULL would not do what you think it does, since it's local to this function. If you wanted to null it out, you'd have to do so in the calling function (by adding k->next = NULL after the free_followers(k->next) call). But you don't need to do that, because "k" in this case will be free'd right after.

And you most certainly do NOT want to free k->follower - this is a pointer to char_data, and you'll want to leave the followers' char_data alone.

The free_followers() function is only called one place ( github.com/tbamud/tbamud/blob/2f12752373...9f8a4/src/db.c#L3246 ) on "ch->followers" right before ch is free'd. Otherwise, you'd need a ch->followers = NULL there, to avoid dereferencing the newly free'd structs.

Please Log in or Create an account to join the conversation.

More
14 May 2016 16:07 #5883 by krell
Replied by krell on topic free_followers() in db.c
Thanks again for the clarification thomas.

Please Log in or Create an account to join the conversation.

Time to create page: 0.230 seconds