pointers - 为什么通过原始指针修改可变引用的值不会违反 Rust 的别名规则?

标签 pointers rust unsafe borrowing

我对 Rust 的别名规则没有特别透彻的理解(据我所知,它们的定义并不明确),但我很难理解是什么让 this code examplestd::slice 文档中可以。我会在这里重复一遍:

let x = &mut [1, 2, 4];
let x_ptr = x.as_mut_ptr();

unsafe {
    for i in 0..x.len() {
        *x_ptr.offset(i as isize) += 2;
    }
}
assert_eq!(x, &[3, 4, 6]);

我在这里看到的问题是,作为&mut 引用的x 可以被编译器假定为唯一的。 x 的内容通过x_ptr 修改,然后通过x 读回,我看不出为什么编译器不能假设x 没有被修改,因为它从未通过唯一现有的 &mut 引用被修改。

那么,我在这里缺少什么?

  • 编译器是否需要假设 *mut T 可能是 &mut T 的别名,即使它通常被允许假设 &mut T 从不给另一个&mut T取别名?

  • unsafe block 是否充当某种别名屏障,编译器假定其中的代码可能修改了范围内的任何内容?

  • 这个代码示例有问题吗?

如果有某种稳定的规则使这个例子没问题,它到底是什么?它的范围是什么?我应该在多大程度上担心别名假设会破坏 不安全 Rust 代码中的随机事物?

最佳答案

免责声明:目前还没有正式的内存模型。1

首先,我想说:

The problem I see here is that x, being an &mut reference, can be assumed to be unique by the compiler.

是的……也不是。 x 如果不是借用,只能假定是唯一的,一个重要的区别:

fn doit(x: &mut T) {
    let y = &mut *x;
    //  x is re-borrowed at this point.
}

因此,目前,我会假设从 x 派生指针会临时“借”x在某种意义上。

当然,在没有正式模型的情况下,这一切都是空话,这也是 rustc 编译器在别名优化方面还不太积极的部分原因:直到定义了正式模型,并检查代码是否匹配它,优化必须是保守的。

1 RustBelt 项目旨在为 Rust 建立一个经过形式验证的内存模型。 Ralf Jung 的最新消息是关于 Stacked Borrows model .


来自拉尔夫(评论):上面例子中的关键点是有一个明确的转自xx_ptr回到x再次。所以 x_ptr在某种意义上是范围借用。应该使用 x , x_ptr , 回到 x回到x_ptr ,那么后者将是未定义的行为:

fn main() {
    let x = &mut [1, 2, 4];
    let x_ptr = x.as_mut_ptr(); // x_ptr borrows the right to mutate

    unsafe {
        for i in 0..x.len() {
            *x_ptr.offset(i as isize) += 2; // Fine use of raw pointer.
        }
    }
    assert_eq!(x, &[3, 4, 6]);  // x is back in charge, x_ptr invalidated.

    unsafe { *x_ptr += 1; }     // BÄM! Used no-longer-valid raw pointer.
}

关于pointers - 为什么通过原始指针修改可变引用的值不会违反 Rust 的别名规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52548161/

相关文章:

C++:如何防止破坏参数中构造的对象?

xpath - 如何使用 SXD-XPath 遍历节点集并打印出每个值?

c++ - 使用迭代器访问结构元素

C:将指向结构的指针传递给函数时出现奇怪的行为

c++ - 指针链接器错误

java - java unsafe中getXXXVolatile与getXXX有什么区别?

ios - Swift 中的 "[self] in"和 "[weak self] in"有什么区别?

rust - 使用借用的结构字段导出 `Deserialize`

tcp - 使用 TcpConnectionNew 时不满足 trait bound `(): futures::Future`

java - 不安全的类加载问题?