2012-02-09 425 views
11

我在學習如何使用list.h的內核鏈表API。爲什麼我們需要list_for_each_safe()來刪除內核鏈表中的節點?

我瞭解到,當使用list_del()而不是使用list_for_each()刪除節點時,我需要使用list_for_each_safe()

代碼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) 

代碼list_for_each()

for (pos = (head)->next; pos != (head); pos = pos->next) 

我注意到他們都是隻是_safe版本需要一個額外的參數非常相似,可以作爲「臨時存儲」 (在此陳述,list.h)。

我明白什麼時候應用功能correcly,_safe刪除版本,正常版本的訪問,但我很好奇額外的參數如何使它「安全」?

考慮下面的,在那裏我刪除使用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); 
    } 

如何讓q幫助刪除?

感謝您的幫助!

+0

我得到了它,沒想到正是這種直接的,謝謝 ! – 2012-02-10 00:11:30

+0

q應該以更好的方式命名..類似於pos_next。 – 2014-09-03 09:27:45

回答

20

即必要的,因爲在內部list_del修改的值pos字段。在你的例子中,循環體甚至可以釋放由pos佔用的內存。假設您將使用循環的不安全版本:pos = pos->next

for (pos = (head)->next; pos != (head); pos = pos->next) 

執行循環體pos指針變爲無效打破了增量表達後。

由於對面,安全的foreach在臨時變量中預先保存的pos->next值,然後是指後者,而不是提領pos

for (pos = (head)->next, n = pos->next; pos != (head); \ 
    pos = n, n = pos->next) 
2
pos = start; 
del(pos); 
pos = pos->next; 

而非

pos = start; 
n = pos->next; 
del(pos); 
pos = n; 

如果德爾()是免費的()和memset(),POS->下是未定義

相關問題