I’m learning how to use the kernel linked-list API from list.h.
I learned that I need to use list_for_each_safe() when deleting nodes off with list_del() instead of using list_for_each().
Code for list_for_each_safe():
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
Code for list_for_each():
for (pos = (head)->next; pos != (head); pos = pos->next)
I notice they both are very similar except that the _safe version takes an extra argument to be used as ‘temporary storage’ (stated here, list.h).
I understand when to apply the function correcly, _safe version for deleting, normal version for accessing, but I’m curious how the extra argument made it ‘safe’?
Consider the following, where I’m deleting every node in a linked list using list_for_each_safe():
struct kool_list{
int to;
struct list_head list;
int from;
};
struct kool_list *tmp;
struct list_head *pos, *q;
struct kool_list mylist;
list_for_each_safe(pos, q, &mylist.list){
tmp= list_entry(pos, struct kool_list, list);
printf("freeing item to= %d from= %d\n", tmp->to, tmp->from);
list_del(pos);
free(tmp);
}
How does giving q help in deleting?
Thanks for any help!
That is necessary because
list_delinternally modifies the value ofposfields. In your example the loop body even frees the memory occupied bypos. Suppose that you would use unsafe version of the loop:After executing the loop body
pospointer becomes invalid breaking the increment expression:pos = pos->next.As opposite, the safe foreach pre-saves the value of
pos->nextin a temporary variable and then refers to the latter instead of dereferencingpos: