Pourquoi avons-nous besoin list_for_each_safe() pour la suppression de nœuds dans le noyau de la liste chaînée?
Je suis en train d'apprendre comment utiliser le noyau de liste liée de l'API de liste.h.
J'ai appris que j'ai besoin d'utiliser list_for_each_safe()
lors de la suppression de nœuds au large avec list_del()
au lieu d'utiliser list_for_each()
.
Code pour 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 pour list_for_each()
:
for (pos = (head)->next; pos != (head); pos = pos->next)
Je remarque qu'ils les deux sont très similaires, sauf que le _safe
version prend un argument supplémentaire pour être utilisés comme stockage temporaire' (indiqué ici, liste.h).
Je comprends quand appliquer la fonction correcly, _safe
version pour la suppression, version normale pour l'accès, mais je suis curieux de voir comment l'argument supplémentaire fait "sûr"?
Considérer le suivant, où je suis la suppression de chaque nœud dans une liste, à l'aide de 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);
}
Comment donner q
aider à le supprimer?
Merci pour toute aide!
- Je l'ai eu, jamais pensé que c'est ce normal, merci !
- q aurait été nommé dans une meilleure façon.. quelque chose comme pos_next.
Vous devez vous connecter pour publier un commentaire.
Qui est nécessaire parce que
list_del
en interne modifie la valeur depos
champs. Dans votre exemple, le corps de la boucle, même libère la mémoire occupée parpos
. Supposons que vous utilisez dangereux version de la boucle:Après l'exécution du corps de la boucle
pos
pointeur devient invalide la rupture de l'opérateur d'incrémentation:pos = pos->next
.Comme ci-contre, le coffre-fort foreach pré-enregistre la valeur de
pos->next
dans une variable temporaire et se réfère ensuite à la dernière place de déréférencementpos
:par opposition à
si del() est gratuit() et memset(), pos->suivant est indéfini