Is ManuallyDrop<Box<T>> with mem::uninitialized defined behavior?
Asked Answered
R

1

6

I have an array with [ManuallyDrop<Box<T>>] which is filled lazily. To realize this, I "initialize" the array with ManuallyDrop::new(mem::uninitialized()).

Is this well-defined behavior as long as I only call ManuallyDrop::drop() on initialized elements?

Raeraeann answered 19/10, 2018 at 13:12 Comment(6)
Yes, this sounds correct. But how are you creating the array?Neogothic
@Peter Vec::with_capacity(), push(mem::uninitialized()), into_boxed_slice()Raeraeann
@Peter oh, pardon. I meant push(ManuallyDrop::new(mem::uninitialized()))Raeraeann
If you are careful, I think you can just use unitialized() for the entire arrayNeogothic
@PeterHall Good point, but I need it to be allocated dynamically. Will use it, if I need a static array.Raeraeann
I'll use MaybeUninit, since I'm on nightly anyway.Raeraeann
N
2

Provided that you do not read from uninitialized memory or create pointers to it, then this should not be UB.

You will need to do some careful bookkeeping to disallow access to uninitialized items, and only drop initialized ones. Adding a new item where there is uninitialized memory needs to be done with ptr::write(), to avoid an invalid drop on the underlying memory. But if you overwrite an existing valid value, then you should not use ptr::write because you need that value to be correctly dropped.

Neogothic answered 19/10, 2018 at 14:50 Comment(5)
I'm unconvinced. github.com/rust-lang/rfcs/pull/1892 suggests that mem::uninitialized is instant UB for any T that has invalid bit patterns, and Box has an invalid bit pattern (all-zeros).Deform
@trentcl But that would only matter if you had a variable of type Box<T> pointing at that uninitialized memory. That is avoidable here though - you only ever refer to a Box<T> after the memory is initialized.Neogothic
I think it would only be a problem if the contents of the box are uninitialized.Neogothic
I think exactly the opposite! An uninitialized Box<T> is instant UB; the referred-to memory being uninitialized would only be a problem when you dereference it. However, I'm not 100% sure of my interpretation since the RFC mostly focuses on !.Deform
@trentcl The uninitialized Box<T> doesn't exist unless you create a variable bound to the memory range. Without a variable binding, it's just a block of uninitialized memory that nothing cares about.Neogothic

© 2022 - 2024 — McMap. All rights reserved.