2012-02-09 14 views
11

Tôi đang tìm hiểu cách sử dụng API danh sách liên kết hạt nhân từ list.h.Tại sao chúng ta cần list_for_each_safe() để xóa các nút trong danh sách liên kết hạt nhân?

Tôi đã học được rằng tôi cần sử dụng list_for_each_safe() khi xóa các nút bằng list_del() thay vì sử dụng list_for_each().

Mã cho 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) 

Mã cho list_for_each():

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

tôi nhận thấy cả hai đều rất giống nhau ngoại trừ việc phiên bản _safe có một đối số phụ được sử dụng như 'lưu trữ tạm thời' (đã nêu ở đây, list.h).

Tôi hiểu khi nào nên áp dụng chức năng sửa đổi, _safe phiên bản để xóa, phiên bản bình thường để truy cập, nhưng tôi tò mò về cách đối số thừa làm cho nó 'an toàn'?

Hãy xem xét những điều sau đây, nơi tôi đang xóa tất cả các nút trong một danh sách liên kết sử dụng 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); 
    } 

Làm thế nào để đưa ra q giúp đỡ trong việc xóa?

Cảm ơn bạn đã trợ giúp!

+0

tôi đã nhận nó, không bao giờ nghĩ rằng nó là thế này thẳng về phía trước, cảm ơn ! –

+0

q nên được đặt tên theo cách tốt hơn .. giống như pos_next. –

Trả lời

20

Đó là cần thiết vì list_del nội bộ thay đổi giá trị của pos trường. Trong ví dụ của bạn, cơ thể vòng lặp thậm chí giải phóng bộ nhớ bị chiếm đóng bởi pos. Giả sử rằng bạn sẽ sử dụng phiên bản không an toàn của vòng lặp:

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

Sau khi thực hiện thân vòng lặp pos con trỏ trở thành không hợp lệ phá vỡ biểu increment: pos = pos->next.

Như ngược lại, các foreach an toàn trước tiết kiệm giá trị của pos->next trong một biến tạm thời và sau đó đề cập đến sau này thay vì dereferencing pos:

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

như trái ngược với

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

nếu del() là miễn phí() và memset(), pos-> tiếp theo là undefined

Các vấn đề liên quan