I'm actually trying to understand how data are stored and loaded using pointers with rust, but when I run this code:
#[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);
}
}
}
The value stored in b
become 0
instead of 5
, and I cannot figure out why this happens and how to solve this.
I think that the problem occurs because the value of a is dropped after the function returns the pointer but I'm not sure if that's right
CodePudding user response:
I think that the problem occurs because the value of a is dropped after the function returns the pointer but I'm not sure if that's right
Well yes, pretty much. The locals of a function only live for the extent of that function (which is why rustc will refuse compiling if you try to return a reference to function-local data), so get_pointer
returns a dangling pointer, serializing and deserializing the pointer does quite literally nothing, and the ptr::read
is UB:
Safety
Behavior is undefined if any of the following conditions are violated:
- src must be valid for reads.
- src must be properly aligned. Use read_unaligned if this is not the case.
- src must point to a properly initialized value of type T.
Running the program using miri unambiguously flags the issue:
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);
| ^^^^^^^^^^^^^^^^^^
I'm actually trying to understand how data are stored and loaded using pointers with rust
Doing it that way is a terrible idea, you're stepping off way into UB land and that means all bets are off, what you observe (to the extent that you can observe anything) has no relations to defined semantics.