Rust 从语义角度看,什么';现在是`&;在锈病中发生的突变?

Rust 从语义角度看,什么';现在是`&;在锈病中发生的突变?,rust,llvm,undefined-behavior,unsafe,Rust,Llvm,Undefined Behavior,Unsafe,正如参考文献所说 打破指针别名规则&mut T和&T遵循LLVM的作用域noalias模型,除非&T包含一个未完成单元 这真是模棱两可。 我想知道noalias在Rust中发生未定义行为的确切时刻是什么时候 它是下面的任何一个,还是别的什么 定义指向同一地址的两个&mut时 当两个&mut指向同一地址时,会生锈吗 当在指向任何其他&mut相同地址的&mut上执行任何操作时 例如,观察到: 不安全{ 让mut x=123使用; 设a=(&mut x as*mut usize).as_mut().u

正如参考文献所说

打破指针别名规则&mut T和&T遵循LLVM的作用域noalias模型,除非&T包含一个未完成单元

这真是模棱两可。
我想知道noalias在Rust中发生未定义行为的确切时刻是什么时候

它是下面的任何一个,还是别的什么

  • 定义指向同一地址的两个
    &mut
  • 当两个
    &mut
    指向同一地址时,会生锈吗
  • 当在指向任何其他
    &mut
    相同地址的
    &mut
    上执行任何操作时
  • 例如,观察到:

    不安全{
    让mut x=123使用;
    设a=(&mut x as*mut usize).as_mut().unwrap();//已创建,但未访问
    设b=(&mut x as*mut usize).as_mut().unwrap();//创建、访问
    *b=666;
    下降(a);
    }
    
    但是如果我修改代码,比如:

    struct不受别名限制
    实际上,多个现有的
    &mut T T
    对同一项使用别名是很常见的

    最简单的例子是:

    fn main() {
       let mut i = 32;
       let j = &mut i;
       let k = &mut *j;
    
       *k = 3;
    
       println!("{}", i);
    }
    
    但是请注意,由于借用规则,您无法同时访问其他别名

    如果您查看
    ManuallyDrop::take
    的实现:

    pub-unsafe-fn-take(插槽:&mut-ManuallyDrop)->T{
    ptr::读取(&slot.value)
    }
    
    您将注意到,没有同时可访问的
    &mut T
    :调用函数会重新借用
    ManuallyDrop
    使
    slot
    成为唯一可访问的可变参考

    为什么Rust中的别名定义如此模糊 这真是模棱两可。我想知道noalias在Rust中发生未定义行为的确切时刻是什么时候

    运气不好,因为按照合同规定:

    不幸的是,Rust实际上还没有定义它的别名模型

    原因是语言团队希望确保他们达成的定义既安全(显然如此)、实用,又不会关闭可能的改进之门。这是一项艰巨的任务

    该公司仍在致力于建立精确的边界,特别是拉尔夫·荣格(Ralf Jung)正在致力于一个名为

    注意:堆叠借用模型是在MIRI中实现的,因此您只需在MIRI中执行代码,就可以根据堆叠借用模型验证代码。当然,堆叠借款仍然是实验性的,所以这不能保证任何事情

    谨慎的建议是什么 我个人赞成谨慎。鉴于确切的模型尚未确定,规则不断变化,因此我建议尽可能采用更严格的解释

    因此,我将
    &mut T T
    的无混叠规则解释为:

    在代码中的任何一点上,如果其中一个是
    &mut T
    ,则范围内不得有两个可访问的引用别名相同的内存

    这是一个实例:<代码>和MUT T >代码>一个实例<代码> t>代码>,其中另一个<代码> &t>代码>或<代码>和MUT T <代码>在范围内,而不使别名无效(通过借用)。


    这很可能过于谨慎,但至少如果别名模型最终比计划的更保守,我的代码仍然有效。

    “您有责任确保此ManuallyDrop不再使用”-这是否引用了您为回答问题而链接的文档?@Cerberus否。在第一个示例中,我们没有取消引用
    a
    ,但它是UB。在第二个例子中,这是与
    ManuallyDrop
    相同的实现,我们也做了两个别名
    &mut
    引用,但只区分了一个,就像
    确保这个ManuallyDrop不再被使用一样,是不是也应该是UB?很抱歉,我只是不明白(2)和(3),(1)的问题很清楚,但我看不出(2)中的“暴露在铁锈中”与(1)中的区别,在(3)中,我不清楚为什么执行操作会导致问题……如果你问
    ManuallyDrop
    实现是否不可靠,那么你应该遵循它的约定。如果您从第二个代码段中删除
    drop
    (这与本合同明显矛盾),可能不会有问题-如果它也是UB,那么,好吧,这是因为
    ManuallyDrop
    是lang项,即编译器的特殊情况。
    pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
        ptr::read(&slot.value)
    }