let r = 42;
unsafe {
let p = &r as *const i32 as *mut i32;
*p += 1;
}
println!("{}", r);
上面的代码是UB
吗?是否有机会rustc
(假设r
是&i32
)以使其最终成为UB
的方式优化此问题?
那↓
let rc = Rc::new(42);
unsafe {
let p = &*rc as *const i32 as *mut i32;
*p += 1;
}
println!("{}", rc);
Rc是一个single-threaded参考计数指针,因此它不是线程安全的。
假设上面的代码是在单个线程中执行的,是否可以以UB
结尾?
答案 0 :(得分:2)
这两种情况肯定都是UB。
这里的主要问题是,对共享引用后面的值的任何更改都是非法的,但UnsafeCell
内部值除外。在第一种情况下,编译器可以轻松地优化更改,只需将r
替换为println
调用即可。
第二种情况比较棘手,但它基于相同的事实。请注意,表达式&*r
的类型为r
,其中Rc<T>
的类型为&T(playground):
use std::rc::Rc;
fn test<T>(r: Rc<T>) {
let _: () = &*r; // error: expected (), found &T
}
诀窍在于,Rc<T>
取消引用T
,因此*r
的类型为T
。
因此,再次将不可变引用视为可变引用。