我实际上是想了解如何使用带有 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
存储在中的值b变为0而不是5,我无法弄清楚为什么会发生这种情况以及如何解决这个问题。
我认为出现问题是因为函数返回指针后 a 的值被删除,但我不确定这是否正确
我认为出现问题是因为函数返回指针后 a 的值被删除,但我不确定这是否正确
嗯,是的,差不多。函数的局部变量仅在该函数的范围内存在(这就是为什么如果您尝试返回对函数局部数据的引用get_pointer,rustc 将拒绝编译),因此返回一个悬空指针,序列化和反序列化该指针实际上什么也不做,并且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);
| ^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
我实际上是想了解如何使用带有 Rust 的指针来存储和加载数据
这样做是一个糟糕的主意,你正在步入 UB 领域,这意味着所有的赌注都结束了,你观察到的东西(就你可以观察到的任何东西而言)与定义的语义没有关系。