我为32位系统做了一个无锁堆栈,使用了比较和交换头指针的classic 算法.为了防止ABA问题,我还必须存储一个单调递增的计数器,并将其与指针交换.在64位系统上,这意味着将计数器填充到指针的未使用的高位中.在32位系统中,这稍微容易一点,因为你可以使用32位指针,32位计数器,并将它们都放入AtomicU64中.

对于64位系统,您可以将填充指针存储为AtomicPtr.如果不屏蔽计数器位,它是无效的,但AFAIK不违反pointer provenance.对于一个32位的系统,你真的别无 Select ,只能使用AtomicU64,然后将它的一半转换为指针.这是Rust中的未定义行为,如果我理解正确的话.编译器做了正确的事情,但它仍然是UB.

我能看到的避免UB的唯一方法是用C语言实现整个代码,因为指针出处是doesn't apply there yet (PDF).或者在汇编语言中,谢天谢地,一个字节仍然只是一个字节.有没有其他方法来解决这个问题,在稳定或夜间 rust 病?

我很想把它作为图书馆出版,但如果它有UB,就没有人会用它了.

我真的希望有一种方法可以告诉编译器:这是一个来源未知的指针,它可以为任何东西起别名,不要插手.

推荐答案

据我所知,要做到这一点,唯一的方法是夜间功能 expose_addr个 和from_exposed_addr.

您可以在功能标志后面使用它们,并在库的文档/自述文件中对此限制进行解释. 就我而言,这是目前图书馆所需的所有尽职调查.

请注意,指针来源仍然是一个热门话题,许多流行的库(example)还没有完全兼容.

还请注意,虽然从技术上讲这可能是Rust中的UB,但LLVM很可能不会利用这一点,因为它的内存模型主要基于C(并且不安全的Rust没有使用C的严格别名规则).只需假设您的所有引用参数都有一个noalias属性,并解释这是否会导致LLVM下的UB,就这么简单;).

然而,这会让MILI陷入困境,它似乎没有一种局部修复错误yet的机制. 幸运的是,由于Miri通常与夜间工具链一起使用, 你go 那里会很好的.

Rust相关问答推荐

即使参数和结果具有相同类型,fn的TypId也会不同

将JSON密钥转换为Polars DataFrame

为潜在的下游实现使用泛型绑定而不是没有泛型绑定的trait

这是不是在不造成嵌套的情况下从枚举中取出想要的变体的惯用方法?

在Rust中是否可以使用Rc自动化约束传播

创建Rust中元对象协议的动态对象 Select /重新分配机制

`RwLockWriteGuard_,T`不实现T实现的特征

std mpsc 发送者通道在闭包中使用时关闭

Rust 异步循环函数阻塞了其他future 任务的执行

Rust Redis 中的 HSET 命令问题

实现泛型的 Trait 方法中的文字

简单 TCP 服务器的连接由对等重置错误,mio 负载较小

没有得到无法返回引用局部变量`queues`的值返回引用当前函数拥有的数据的值的重复逻辑

如果不满足条件,如何在 Rust 中引发错误

使用 `clap` 在 Rust CLI 工具中设置布尔标志

强制特征仅在 Rust 中的给定类型大小上实现

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

如何获得对数组子集的工作可变引用?

如何在 C++ 和 Rust 之间共享 pthread 同步原语?

返回 &str 但不是 String 时,borrow 时间比预期长