2013-10-02 64 views
1

我正在追蹤一些我沒寫的代碼中的幾個奇怪的Coverity bug。在一個案例中,我們使用TAILQ_FIRST和TAILQ_REMOVE在一個循環中,像這樣:TAILQ_REMOVE爲什麼不重置頭指針?

while (!TAILQ_EMPTY(&queue)) 
{ 
    item* entry = TAILQ_FIRST(&queue); 
    TAILQ_REMOVE(&queue, entry, next); 
    free(entry); 
} 

Coverity的抱怨了很多關於這一點,說我是雙釋放。然而,看着TAILQ_REMOVE,這可能是正確的:(/usr/include/x86_64-linux-gnu/sys/queue.h在我的Linux機器)

#define TAILQ_REMOVE(head, elm, field) do {        \ 
     if (((elm)->field.tqe_next) != NULL)       \ 
       (elm)->field.tqe_next->field.tqe_prev =     \ 
        (elm)->field.tqe_prev;        \ 
     else               \ 
       (head)->tqh_last = (elm)->field.tqe_prev;    \ 
     *(elm)->field.tqe_prev = (elm)->field.tqe_next;     \ 
} while (/*CONSTCOND*/0) 

不像其他一些相關的宏,我沒有看到任何這裏重置tqe_first如果我刪除頭節點。因此,我會繼續在我的循環中獲取已刪除的節點。

但我真的不明白髮生了什麼事。儘管出現Coverity警告,此代碼仍然可以正常工作。

在網上找到這樣的例子很困難。

+0

可能有助於添加警告覆蓋率給出 – nos

回答

2

這是有效的,因爲tqe_prev是一個指向指針的指針。如果非空,則隊列中的第一個元素將其tqe_prev字段初始化爲tqe_first的地址。因此,解引用它並將其分配給它,就像在宏的最後一行中一樣,如果要刪除第一個元素,則最終將設置tqh_first。 (通常,tqe_prev將具有前一個節點的指針tqe_next的地址。)