我实际上试图理解如何使用rust指针存储和加载数据,但是当我运行这段代码:
#[cfg(test)]
mod tests{
fn get_pointer<T>(a:T) -> *const i32{
ptr::addr_of!(a)
}
#[test]
fn f(){
unsafe {
let a = 5;
let pointer = get_pointer(a);
let encoded = bincode::serialize(&(pointer as usize)).unwrap();
let decoded = bincode::deserialize::<usize>(&encoded[..]).unwrap() as *const i32;
let b = std::ptr::read(decoded);
assert_eq!(a, b);
}
}
}
存储在b
中的值变成了0
而不是5
,我不知道为什么会发生这种情况,如何解决
我认为问题发生是因为a的值在函数返回指针后被删除但我不确定这是否正确
我认为问题发生是因为a的值在函数返回指针后被删除但我不确定这是否正确
嗯,是的,差不多。函数的局部变量只存在于该函数的范围内(这就是为什么如果您试图返回对函数局部数据的引用, rustc将拒绝编译),因此get_pointer
返回一个悬浮指针,对指针进行序列化和反序列化实际上什么都不做,并且ptr::read
是UB:
安全如果违反下列任何条件,则未定义行为:
- src必须对读取有效。
- src必须正确对齐。如果不是这种情况,请使用read_unaligned
- src必须指向一个正确初始化的t类型值。
使用miri运行程序明确标记问题:
error: Undefined Behavior: pointer to alloc1416 was dereferenced after this allocation got freed
--> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:703:9
|
703 | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to alloc1416 was dereferenced after this allocation got freed
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: inside `std::ptr::read::<i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:703:9
note: inside `main` at src/main.rs:12:17
--> src/main.rs:12:17
|
12 | let b = ptr::read(decoded);
| ^^^^^^^^^^^^^^^^^^
我实际上是在尝试理解如何使用rust指针存储和加载数据
这样做是一个糟糕的主意,你正在踏入UB的土地,这意味着所有的赌注都没有了,你观察到的(在某种程度上你可以观察到任何东西)与定义的语义没有关系。