从语义学的角度来看,Rust中的"&mut "noalias的未定义行为是什么时候发生的?

问题描述 投票:3回答:1

正如Rust参考文献所说

打破指针别名规则。&mut T和&T遵循LLVM的scoped noalias模型,除非&T包含一个UnsafeCell。

这真的很模棱两可。我想知道的是,在什么时候,一个未定义行为的 &mut Noalias发生在Rust。

是以下任何一种,还是其他什么?

  1. 当定义两个 &mut 指向同一个地址的?
  2. 当两个 &mut 指向同一个地址的东西,会不会生锈?
  3. 当对一个 &mut 指向任何其他公司的同一地址的 &mut

例如: 此代码 是观察性的UB。

unsafe {
    let mut x = 123usize;
    let a = (&mut x as *mut usize).as_mut().unwrap(); // created, but not accessed
    let b = (&mut x as *mut usize).as_mut().unwrap(); // created, accessed
    *b = 666;
    drop(a);
}

但是,如果我修改代码像 这个:

struct S<'a> {
    ref_x: &'a mut usize
}

fn main() {
    let mut x = 123;
    let s = S { ref_x: &mut x }; // like the `T` in `ManuallyDrop<T>`
    let taken = unsafe { std::ptr::read(&s as *const S) }; // like `ManuallyDrop<T>::take`
    // at thist ime, we have two `&mut x`
    *(taken.ref_x) = 666;
    drop(s);
    // UB or not?
}

第二版也是UB吗?第二版完全是一样的实现,以达到以下目的 std::mem::ManuallyDrop. 如果第二个版本是UB,是否是一个安全漏洞的 std::mem::ManuallyDrop<T>?

rust llvm undefined-behavior unsafe
1个回答
1
投票

别名限制是什么

其实常见的有 多重 现有 &mut 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(slot: &mut ManuallyDrop<T>) -> T {
    ptr::read(&slot.value)
}

你会注意到,没有 同时 无障碍 &mut T:调用函数重播 ManuallyDrop 制作 slot 唯一可访问的可变引用。

为什么Rust中的别名定义得如此不明确?

这真的是模棱两可。我想知道,一个未定义的行为到底是在什么时候发生的?&mut Noalias发生在Rust。

运气不好,因为正如在 Nomicon:

不幸的是,Rust还没有真正定义它的别名模型。

原因是语言团队希望确保他们达成的定义既是 安全的 (显然如此)。实用但却没有 关门 到可能的完善。这是一个很高的要求。

铁锈不安全规范准则工作组 仍在研究建立确切的边界,特别是Ralf Jung正在研究一种叫做 "别名 "的操作模型。叠加借款.

注意:Stacked Borrows模型是在MIRI中实现的,因此你可以通过在MIRI中执行你的代码来验证你的代码与Stacked Borrows模型。当然Stacked Borrows还是实验性的,所以这并不能保证什么。

推荐什么注意事项

我个人赞同谨慎行事。由于具体型号未明确,所以规则是 千变万化 因此,我建议采取 更严格 解释的可能。

因此,我将无锯齿规则解释为 &mut T 作为。

在代码中的任何时候,在作用域中不得有两个可访问的引用,它们别名为同一存储器,如果其中一个是: &mut T.

也就是说,我认为 形成 a &mut T 到一个实例 T 为此 &T&mut T 在范围内 使别名无效(通过借用)是不妥当的。

很可能是过于谨慎了,但至少如果别名模式最后比计划中更保守,我的代码还是有效的。

© www.soinside.com 2019 - 2024. All rights reserved.