通过* mut T在不安全的锈蚀中突变&T是UB吗?

时间:2019-05-04 06:56:56

标签: rust

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结尾?

1 个答案:

答案 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

因此,再次将不可变引用视为可变引用。