【问题标题】:Why doesn't TAILQ_REMOVE reset the head pointer?为什么 TAILQ_REMOVE 不重置头指针?
【发布时间】:2013-10-02 18:46:07
【问题描述】:

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

#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 警告,此代码似乎仍然有效。

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

【问题讨论】:

  • 可能有助于添加警告覆盖率

标签: c queue


【解决方案1】:

这是因为tqe_prev 是一个指向指针的指针。如果非空,则队列中的第一个元素将其tqe_prev 字段初始化为tqe_first 的地址。因此,取消引用并分配给它,就像在宏的最后一行中所做的那样,如果您要删除第一个元素,最终将设置 tqh_first。 (通常,tqe_prev 将具有前一个节点的tqe_next 指针的地址。)

【讨论】:

    猜你喜欢
    • 2012-01-10
    • 2010-10-16
    • 1970-01-01
    • 2018-10-11
    • 2021-12-26
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    相关资源
    最近更新 更多