C 为什么';t TAILQ_移除并重置头部指针?

C 为什么';t TAILQ_移除并重置头部指针?,c,queue,C,Queue,我正在追踪一些我没有编写的代码中的一些奇怪的Coverity bug。在一种情况下,我们在循环中使用TAILQ_FIRST和TAILQ_REMOVE,如下所示: while (!TAILQ_EMPTY(&queue)) { item* entry = TAILQ_FIRST(&queue); TAILQ_REMOVE(&queue, entry, next); free(entry); } Coverity对此抱怨很多,说我是双重自由。然而,看看

我正在追踪一些我没有编写的代码中的一些奇怪的Coverity bug。在一种情况下,我们在循环中使用TAILQ_FIRST和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机器上)

与其他一些相关宏不同,如果我删除head节点,我在这里看不到任何会先重置
tqe_
。因此,我将继续在循环中获取已删除的节点

但我真的不明白发生了什么。尽管存在Coverity警告,但此代码似乎仍然有效


很难在网上找到这方面的例子

这是因为
tqe\u prev
是指向指针的指针。如果非空,队列中的第一个元素将其
tqe\u prev
字段初始化为
tqe\u first
的地址。因此,如果要删除第一个元素,则如在宏的最后一行中所做的那样,取消对它的引用并分配给它,最终将设置
tqh\u first
。(通常,
tqe\u prev
将具有上一个节点的
tqe\u next
指针的地址。)

可能有助于添加警告
#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)