Zz *_*Tux 5 unsafe llvm undefined-behavior rust
正如 Rust 参考文档所说
\n\n\n\n\n违反指针别名规则。&mut T 和 &T 遵循 LLVM\xe2\x80\x99s 作用域 noalias 模型,除非 &T 包含 UnsafeCell。
\n
实在是太暧昧了。
\n我想知道 Rust 中 noalias 的未定义行为发生在什么时刻&mut
。
是下面的任何一个,还是其他什么?
\n\n\n\n\n\n
\n- 当定义两个
\n&mut
指向同一地址时?- 当两个
\n&mut
指向同一地址的对象暴露于锈迹时?- \n
&mut
当对指向任何其他地址的同一地址执行任何操作时&mut
?
例如,这段代码显然是 UB 的:
\n\nunsafe {\n let mut x = 123usize;\n let a = (&mut x as *mut usize).as_mut().unwrap(); // created, but not accessed\n let b = (&mut x as *mut usize).as_mut().unwrap(); // created, accessed\n *b = 666;\n drop(a);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n但是如果我像这样修改代码怎么办:
\n\nstruct S<\'a> {\n ref_x: &\'a mut usize\n}\n\nfn main() {\n let mut x = 123;\n let s = S { ref_x: &mut x }; // like the `T` in `ManuallyDrop<T>`\n let taken = unsafe { std::ptr::read(&s as *const S) }; // like `ManuallyDrop<T>::take`\n // at thist ime, we have two `&mut x`\n *(taken.ref_x) = 666;\n drop(s);\n // UB or not?\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n第二个版本也是UB吗?\n第二个版本与std::mem::ManuallyDrop
的实现完全相同。如果第二个版本是UB,是否存在安全漏洞?std::mem::ManuallyDrop<T>
实际上,同一个项目有多个别名是很常见的。&mut T
最简单的例子是:
fn main() {
let mut i = 32;
let j = &mut i;
let k = &mut *j;
*k = 3;
println!("{}", i);
}
Run Code Online (Sandbox Code Playgroud)
但请注意,由于借用规则,您无法同时访问其他别名。
如果你看看以下的实现ManuallyDrop::take
:
Run Code Online (Sandbox Code Playgroud)pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { ptr::read(&slot.value) }
您会注意到,没有同时可访问的&mut T
:调用函数重新借用,ManuallyDrop
从而形成slot
唯一可访问的可变引用。
实在是很暧昧。我想知道
&mut
Rust 中 noalias 的未定义行为发生在什么时刻。
运气不好,因为正如Nomicon中所指定的:
不幸的是,Rust 还没有真正定义它的别名模型。
原因是语言团队希望确保他们得出的定义既安全(显然如此)、实用,又不会关闭可能的改进之门。这是一个艰巨的任务。
Rust不安全代码指南工作组仍在努力建立确切的边界,特别是 Ralf Jung 正在研究一种名为Stacked Borrows的别名操作模型。
注意:Stacked Borrows 模型是在 MIRI 中实现的,因此您只需在 MIRI 中执行代码即可根据 Stacked Borrows 模型验证您的代码。当然,Stacked Borrows 仍处于实验阶段,因此这并不能保证任何事情。
我个人持谨慎态度。鉴于确切的模型未指定,规则不断变化,因此我建议尽可能采取更严格的解释。
因此,我将无别名规则解释为&mut T
:
在代码中的任何一点,如果其中一个是 ,则作用域中不应有两个可访问的引用对同一内存进行别名
&mut T
。
也就是说,我认为在不使别名无效(通过借用)的情况下,将a形成为另一个or位于范围内的&mut T
实例是不正确的。T
&T
&mut T
它很可能过于谨慎,但至少如果别名模型最终比计划的更加保守,我的代码仍然有效。
归档时间: |
|
查看次数: |
210 次 |
最近记录: |