首页 > 解决方案 > UB 是否通过不安全的生锈中的 *mut T 来突变 &T?

问题描述

let r = 42;
unsafe {
    let p = &r as *const i32 as *mut i32;
    *p += 1;
}
println!("{}", r);

是上面的代码UB吗?是否有机会rustc(假设r是 a &i32)会以最终结果为的方式优化它UB

这个呢↓

let rc = Rc::new(42);
unsafe {
    let p = &*rc as *const i32 as *mut i32;
    *p += 1;
}
println!("{}", rc);

Rc 是一个单线程引用计数指针,因此它不是线程安全的。
假设上面是在单个线程中执行的,它最终会是UB

标签: rust

解决方案


这两种情况都绝对是UB。

这里的主要问题是,对共享引用背后的值的任何更改都是非法的,UnsafeCell内部值除外。编译器可以很容易地优化掉第一种情况下的变化,只需替换rprintln调用。

第二种情况有点棘手,但它基于相同的事实。请注意,表达式&*rr类型Rc<T>为 ,其类型为 &T (操场):

use std::rc::Rc;

fn test<T>(r: Rc<T>) {
    let _: () = &*r; // error: expected (), found &T
}

诀窍在于Rc<T>derefs to T,所以*r有 type T

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


推荐阅读