先决条件:
#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))
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)。这种推理是否合理,还是我不知何故弄错了?或者标准的某些部分是否被普遍认为不值得遵循?
最佳答案
编译内核时所做的附加断言。这些实际上到处都在使用。
编译器选项告诉编译器这些都是真的。 (事实上,第一个通常在平面模型中被假设为真,内核就是这样。)
标志传递给
gcc
是 -fno-delete-null-pointer-checks
.空指针优化更改引用:https://lwn.net/Articles/342420/
关于c - Linux内核列表实现会导致UB吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64859526/