在指向结构的指针上使用 AtomicPtr::compare_exchange 时的行为是啥?

Posted

技术标签:

【中文标题】在指向结构的指针上使用 AtomicPtr::compare_exchange 时的行为是啥?【英文标题】:What is the behavior of AtomicPtr::compare_exchange when used on a pointer to a struct?在指向结构的指针上使用 AtomicPtr::compare_exchange 时的行为是什么? 【发布时间】:2021-05-25 06:37:24 【问题描述】:

compare_exchange 的这种用法会产生已定义的行为吗?

use std::sync::atomic::AtomicPtr, Ordering;

struct Dummy 
    foo: i64,
    bar: i64,


fn main() 
    let ptr = &mut Dummy  foo: 1, bar: 2 ;
    let some_ptr = AtomicPtr::new(ptr);

    let other_ptr = &mut Dummy  foo: 10, bar: 10 ;

    let value = some_ptr.compare_exchange(ptr, other_ptr, Ordering::SeqCst, Ordering::Relaxed);

如果已定义,定义的行为是什么? Rust 会在 x86_64 等受支持的架构上使用双宽 CAS 进行上述操作吗?

【问题讨论】:

AtomicPtr::compare_exchange 仅比较和交换 指针,它是 64 位的,没有理由与 CAS 进行双精度操作。 是的,我对 compare_exchange 的理解是错误的。感谢您清理它 【参考方案1】:

compare_exchange 的这种用法会产生已定义的行为吗?

除非编译器或标准库中出现错误,否则安全的 Rust 永远不会导致 C 和 C++ 意义上的未定义行为。此外,创建和操作指针始终是安全的,它只是取消引用它们或将它们转换为需要显式 unsafe 的引用,因为程序员需要提供编译器无法验证的保证。当然,对安全函数的特定调用是否符合您的预期是另一回事。

如果定义了,定义的行为是什么?

行为是由文档指定的:将some_ptr 指向的地址与ptr 指向的地址进行比较,如果它们匹配,some_ptr 会自动更新为指向@987654326 提供的地址@。在任何一种情况下都会返回前一个指针。由于您的代码从ptr 初始化some_ptr,并且没有创建可以更改它的线程,因此将导致some_ptr 指向other_ptr 提供的地址,并返回ptr

Rust 会在 x86_64 等受支持的架构上使用双宽度 CAS 进行上述操作吗?

AtomicPtr::compare_exchange() 只比较和交换指针,它与usize 一样宽(现代硬件上为 64 位),没有理由使用双宽 CAS。

但我想我理解混乱是如何产生的:compare_exchange 的文档谈到了指针的。这个“值”不是指向数据的值,它只是底层的*mut T指针,它只代表一个内存地址。就像AtomicBool 的值是boolAtomicPtr 的值是一个指针。

如果文档使用“ 指向的地址”而不是“ 的值”,则文档会更准确一些,但这会更冗长。 (较短的“ 的地址”将再次模棱两可,因为它可能被理解为指向指针本身所在的地址。)

【讨论】:

以上是关于在指向结构的指针上使用 AtomicPtr::compare_exchange 时的行为是啥?的主要内容,如果未能解决你的问题,请参考以下文章

指向结构的指针上的点运算符

为啥宁愿使用指向结构的指针而不是链表中的常规结构类型变量?

使用指向第一个成员的指针调用 free 是不是有效?

结构中指向数组的 cudaFree 指针上的 CUDA 分段错误

何时使指针指向堆上的结构与堆栈上的结构? [复制]

结构体指针在使用完free后,该指针所指向的内存区域是啥,这个指针是变成了NULL,还是野指针。