使用list时易错的误区

linux的list结构简单灵活,所以也常常被用在用户空间。但在使用的时候有个需要注意的小地方,试看下面这段代码:

    list_head   *pos;

    list_for_each(pos, &queue->posted) {
        request_head_t   *post_req  = list_entry(pos, request_head_t, list);
        req_destroy((request_t*)post_req, 1);
        list_del_init(pos);
    }

其中posted定义为:list_head类型。

其中list_for_each, list_del_init, list_entry都是从内核中复制粘贴过来的,冷眼一看似乎没什么问题。执行的时候可以发现这段代码是死循环,why??内核代码有问题?!

其实如果这段代码不是通过宏的方式封装的话,一眼就能看出来bug,但被封装后可就不容易发现了。首先,让我们看一下list_for_each和list_del_init是如何定义的:

#define list_for_each(pos, head) /
 for (pos = (head)->next; pos != (head); pos = pos->next)

static inline void list_del(struct list_head *entry)
{
 __list_del(entry->prev, entry->next);
 entry->next = LIST_POISON1;
 entry->prev = LIST_POISON2;
}

static inline void list_del_init(struct list_head *entry)
{
 __list_del(entry->prev, entry->next);
 INIT_LIST_HEAD(entry);
}

把代码替换进去就能发现,list_for_each操作后续还要继续使用pos的内容呢,如果这个时候把pos销毁或修改,那么后面发生的事情就不确定了,可能死循环也可能内存非法访问。。。

所以上面那段代码应该修改为:

    while (!list_empty(&queue->posted)) {
        pos = queue->posted.next;
        request_head_t   *post_req  = list_entry(pos, request_head_t, list);
        req_destroy((request_t*)post_req, 1);
        list_del_init(pos);       
    }

:-)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值