#[derive(Clone, Debug)]
pub struct Elem {
inner: u8,
}
#[derive(Clone)]
#[repr(transparent)]
pub struct Dict{
list : Vec<Elem>,
}
impl Dict {
pub fn new() -> Self {
Self {
list: Vec::new()
}
}
pub fn set(&mut self, elem: Elem) {
self.list.push(elem)
}
pub fn len(&self) -> usize {
self.list.len()
}
#[allow(invalid_reference_casting)]
pub fn get_mut_unchecked(&self) -> &mut Self {
unsafe {
let ptr1 = self as *const Self;
let ptr2 = ptr1 as *mut Self;
&mut *ptr2
}
}
}
fn func(dict: &Dict) {
let this = dict.get_mut_unchecked();
let elem = Elem{inner:42};
this.set(elem);
}
fn main() {
let dict = Dict::new();
func(&dict);
println!("Hello, world! => len:{}", dict.len());
}
// --------------------- 我希望能通过回调获取数据,也就是dict.len()!=0; 但是实际上在release模式下传入dict的数据被优化掉了
rust版本:
rustc 1.80.0-nightly (867900499 2024-05-23)
binary: rustc
commit-hash: 8679004993f08807289911d9f400f4ac4391d2bc
commit-date: 2024-05-23
host: x86_64-unknown-linux-gnu
release: 1.80.0-nightly
LLVM version: 18.1.6
1
共 2 条评论, 1 页
评论区
写评论非常好bug
实际上需要使用
UnsafeCell
:get_mut_unchecked
本质是就是实现“内部可变性”的,但是这个本身是违反rust编译器的引用规则的,会被视为未定义行为,如果编译器判断某些代码对程序最终状态不产生影响,就会被优化掉。UnsafeCell
就是rust原语,专门用来实现内部可变性的,使用了UnsafeCell
的结构也将获得对应的内部可变(&T -> &mut T),并且保证编译器不会错误优化。如果func(dict: &Dict) 改成 func(dict: &mut Dict) 则上述问题就没有了