Converting raw pointer from Box::into_raw to a &mut

I'm passing ownership of a Box over FFI, but occasionally need to borrow it back. The obvious way would be to call as_ref() (or as_mut()) on the pointer, like this: Rust Playground

This seems to work fine but is it guaranteed to work in all cases? Or does it depend on implementation details and I need to do something like this?

let borrowed_box = unsafe { Box::from_raw(ptr); }
borrowed_box.do_stuff(); // via Deref/DerefMut
std::mem::forget(borrowed_box); // so we don't actualy drop the box yet

as_ref and as_mut are the correct semantics here. Using Box::from_raw implies that you're retaking ownership of the value, and may even be incorrect (since Box assumes a unique pointer - reviewing with miri I think it's likely fine, but I still think it's better to stick to as_ref / as_mut for human legibility purposes).

1 Like

Using as_ref or as_mut pointer methods, or equivalently just dereferencing unsafe { (*borrowed_box).do_stuff() } (which can skip the null handling, too, but also it's less explicit about the mutable or immutable nature of the access) is the right thing to do, and should be officially allowed without incorrectly depending on any "implementation details" AFAIK. Using Box::from_raw like you did has the additional problem of dropping the box in case of panic (though IIRC panics can be problematic with FFI anyways). If you wanted to use from_raw without incorrect panic handling - and this is a general tip for many use-cases of mem::forget, you could wrap the value in ManuallyDrop instead (before the code section that could panic).

1 Like

Thanks! I was overcomplicating this for no reason. Since Box<T>::into_raw returns a *mut T, it has to be usable as a *mut T, right? :slight_smile: Regardless if it passed through FFI on the way.

The type *mut T itself doesn't automatically mean that it's ever safe to dereference it, on the other hand. I'd also say the documentation could be even more clear about this. On the other hand, multiple parts of the existing documentation can at least be understand to imply you can use this pointer normally too access the contents of the box.

It's good to be cautious though, unsafe Rust does for sure feature many instances of things you aren't allowed to do that can be surprising, depending on your background. So given you weren't sure of the details, I think asking here was a very good idea.

2 Likes