1
votes

I have a function that coverts a Box::into_raw result into a u64. I later 're-Box' with from the u64.

// Somewhere at inception
let bbox = Box::new(MyStruct::from_u32(1u32).unwrap());
let rwptr = Box::into_raw(bbox);
let bignum_ptr = rwptr as u64;

// Later in life
let rehyrdrate: Box<MyStruct> = unsafe {
    Box::from_raw(bignum_ptr as *mut MyStruct)
};

What I would like to do is 're-Box' that bignum_ptr again, and again, as needed. Is this possible?

2
What should happen when rehydrate goes out of scope? Should the memory allocated for the box be freed or not?user4815162342
The holder of bignum_ptr would be responsible for dropping,Frank C.
In that case rehydrate should be a reference, not a box: let rehyrdrate: &MyStruct = unsafe { &*(bignum_ptr as *const MyStruct) };. When you need to free the box (and know that no outstanding references exist), you can use drop(Box::from_raw(bignum_ptr as *mut MyStruct)).user4815162342
@user4815162342 thanks... I will give that a try!Frank C.
There should rarely be any reason to cast a raw pointer to an integer, but if you have to (some FFIs require it), you should use usize instead of u64.trentcl

2 Answers

2
votes

A box owns the data it points to, and will deallocate/drop it when it goes out of scope, so if you need use the same pointer in more than one place, Box is not the correct type. To support multiple "revivals" of the pointer, you can use a reference instead:

// safety contract: bignum_ptr comes from a valid pointer, there are no
// mutable references
let rehydrate: &MyStruct = unsafe { &*(bignum_ptr as *const MyStruct) };

When the time comes to free the initial box and its data (and you know that no outstanding references exist), only then re-create the box using Box::from_raw:

// safety contract: bignum_ptr comes from a valid pointer, no references
// of any kind remain
drop(unsafe { Box::from_raw(bignum_ptr as *const MyStruct) });
0
votes

What I would like to do is 're-Box' that bignum_ptr again, and again, as needed. Is this possible?

If you mean creating many boxes from the same pointer without taking it out each time, no.

If you mean putting it in and out repeatedly and round-tripping every time via an integer, probably yes; however, I would be careful with code like that. Most likely, it will work, but be aware that the memory model for Rust is not formalized and the rules around pointer provenance may change in the future. Even the C and C++ standards (from where Rust memory model comes from) have open questions around those, including round-tripping via an integer type.

Furthermore, your code assumes a pointer fits in a u64, which is likely true for most architectures, but maybe not all in the future.

At the very least, I suggest you use mem::transmute rather than a cast.


In short: don't do it. There is likely a better design for what you are trying to achieve.