c - Linux内核列表实现会导致UB吗?

标签 c list linked-list linux-kernel

先决条件:

  • 根据 C standard , 会产生无效指针的指针算术会导致未定义的行为。
  • Linux源代码seems to conform使用 C 标准,希望与大多数架构兼容。
  • Linux's list implementation包含以下代码(保留格式,另一个问题的想法可能是如何使用 Stackoverflow 语法设置适当的制表宽度):

  • #define list_entry(ptr, type, member) \
        container_of(ptr, type, member)
    
    #define list_next_entry(pos, member) \
        list_entry((pos)->member.next, typeof(*(pos)), member)
    
    #define list_first_entry(ptr, type, member) \
        list_entry((ptr)->next, type, member)
    
    #define list_entry_is_head(pos, head, member)               \
        (&pos->member == (head))
    
    #define list_for_each_entry(pos, head, member)              \
        for (pos = list_first_entry(head, typeof(*pos), member);    \
             !list_entry_is_head(pos, head, member);            \
             pos = list_next_entry(pos, member))
    
  • 上述列表实现的典型用例是具有 say 类型 struct A 的结构。 , 包含类型为 struct B 的结构列表的头部.

  • : 让我们假设 offsetof(struct B, entry_in_list) > offsetof(struct A, list_head)并实现了以下循环:
    struct A* A_ptr = something_meaningful;
    struct B* pos = NULL;
    list_for_each_entry(pos, &A_ptr->list_head, entry_in_list) {
      do_something();
    }
    
    然后最后(在循环退出之前)评估 list_next_entry(pos, member)将扩展到:
    container_of(A_ptr->list_head, struct B, entry_in_list) = 
     = (char*)A_ptr->list_head - offsetof(struct B, entry_in_list) =
     = (char*)A_ptr + offsetof(struct A, list_head) - offsetof(struct B, entry_in_list) 
    
    ,根据我们的假设,它会指向 A 结构体之前的区域。假设这个区域不包含分配的内存,结果container_of()宏将是一个无效的指针,从而导致 Linux 中的 UB(在一般情况下为 OFC)。这种推理是否合理,还是我不知何故弄错了?
    或者标准的某些部分是否被普遍认为不值得遵循?

    最佳答案

    编译内核时所做的附加断言。这些实际上到处都在使用。

  • 一个指针可能加载了一个未分配的地址。您可以在每个系统调用条目上看到这一点。处理此类指针时必须特别小心,因为取消引用它们可能比崩溃更糟糕。
  • 不保证取消引用 NULL 指针会崩溃;并且不允许编译器假设取消引用 NULL 的路径是不可达的。 (这个是在 NULL 指针优化删除安全检查之后添加的。)在某些体系结构上实际上有一些东西;在其他架构上,它只是另一个用户模式指针。

  • 编译器选项告诉编译器这些都是真的。 (事实上​​,第一个通常在平面模型中被假设为真,内核就是这样。)
    标志传递给 gcc-fno-delete-null-pointer-checks .空指针优化更改引用:https://lwn.net/Articles/342420/

    关于c - Linux内核列表实现会导致UB吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64859526/

    相关文章:

    sql - 列出数据库、表、字段、存储过程

    c - 节点->指针=指针与使用memcpy的节点->指针

    java - 如何找到链表的最大/最小元素

    C - 图中的 AddEdge 函数

    c - 读取包含单词的 txt 文件的行

    .net - 从字符串数组中删除项目

    c# - IQueryable、ICollection、IList 和 IDictionary 接口(interface)之间的区别

    c - 当我的 fgets 输入超过指定的缓冲区大小时,我的(非常简单的)程序似乎表现出奇怪的行为

    c - 如何从 C 中的字符串解析标记?

    c - 如何在链表中将节点从头移动到尾? C