Rust:从原始指针加载值

1 pointers rust

我实际上是想了解如何使用带有 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 的值被删除,但我不确定这是否正确

Mas*_*inn 5

我认为出现问题是因为函数返回指针后 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 领域,这意味着所有的赌注都结束了,你观察到的东西(就你可以观察到的任何东西而言)与定义的语义没有关系。