Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upHow to safely initialize an array of Vec with MaybeUninit doc example #54542
Comments
This comment has been minimized.
This comment has been minimized.
|
What would the example look like? Something like this? let arr: [MaybeUninit<Vec<u8>>; 5] = [MaybeUninit::uninitialized(); 5];
for v in &mut arr {
v.set(vec![]);
}
let arr: [Vec<u8>; 5] = mem::transmute(arr);cc @RalfJung |
This comment has been minimized.
This comment has been minimized.
leonardo-m
commented
Sep 24, 2018
|
As arr array length is better to use 50 instead of 5, because Default:default goes up to about 30. |
frewsxcv
added
T-libs
T-doc
labels
Sep 25, 2018
This comment has been minimized.
This comment has been minimized.
|
One gotcha is that the example doesn't even work as-is because If |
This comment has been minimized.
This comment has been minimized.
|
In 7c37c6d#diff-322c42fd5e8ec8e8f8093261d59a5782R87, @eddyb and @RalfJung mention that let mut arr: MaybeUninit<[Vec<u8>; 5]> = MaybeUninit::uninitialized();
for i in 0..5 {
ptr::write(&mut arr.get_mut()[i], vec![]);
}
let arr: [Vec<u8>; 5] = arr.into_inner();...if it is safe to get a pointer or reference to the uninitialized inner value or its fields/elements, as long as this pointer isn't used to read from uninitialized portions of the value. It would only be safe to read from an element after it is initialized, and only safe to read from the whole (e.g. using Note that the expression (arr.as_mut_ptr() as *mut Vec<u8>).offset(i).write(vec![]); |
mbrubeck
referenced this issue
Sep 27, 2018
Open
Possible UB from use of uninitialized `[&T; N]` #126
This comment has been minimized.
This comment has been minimized.
|
So would this be a valid example of how to initialize an array of Vecs then? #![feature(maybe_uninit)]
use std::mem::{self, MaybeUninit};
fn main() {
let mut arr: [MaybeUninit<Vec<u8>>; 50] = {
// The compiler complains about `Copy` bounds if we try to directly
// create a `[MaybeUninit<Vec<u8>>; 50]`, so we use the fact that
// MaybeUninit<[T; N]> == [MaybeUninit<T>; N] to work around that
let arr: MaybeUninit<[Vec<u8>; 50]> = MaybeUninit::uninitialized();
unsafe { mem::transmute(arr) }
};
// Initialize the elements one at a time. The `Iterator` trait isn't
// implemented for arrays over size 32 (integer generics when!?),
// so let's use good ol' indexing instead.
for idx in 0..arr.len() {
arr[idx].set(vec![]);
}
// Now that everything is initialized (and they'd better be fully
// initialized or things WILL blow up here), we can transmute to
// a fully valid array of Vecs
let arr: [Vec<u8>; 50] = unsafe { mem::transmute(arr) };
// `Debug` is also unimplemented for arrays of this size, so let's
// index-loop again to show our completed work!
for idx in 0..arr.len() {
println!("Index {}: {:?}", idx, arr[idx]);
}
} |
This comment has been minimized.
This comment has been minimized.
leonardo-m
commented
Sep 27, 2018
|
Is it worth adding to the Rust std lib a helper macro like this, to simplify the creation of arrays of noncopy values? |
This comment has been minimized.
This comment has been minimized.
My code from above was meant to be an entire solution, without any transmuting necessary. Here's a complete example program: use std::mem::MaybeUninit;
fn main() {
const N: usize = 5;
let arr: [Vec<u8>; N] = unsafe {
let mut arr = MaybeUninit::uninitialized();
for i in 0..N {
(arr.as_mut_ptr() as *mut Vec<u8>).add(i).write(vec![]);
}
arr.into_inner()
};
for idx in 0..arr.len() {
println!("Index {}: {:?}", idx, arr[idx]);
}
} |
This comment has been minimized.
This comment has been minimized.
|
Ah nice, that's way more concise. |
This comment has been minimized.
This comment has been minimized.
|
@mbrubeck One extremely subtle point about your code is the Nice to have no transmute, though use std::mem::MaybeUninit;
fn main() {
const N: usize = 5;
let arr: [Vec<u8>; N] = unsafe {
let mut arr: MaybeUninit<[Vec<u8>; N]> = MaybeUninit::uninitialized();
let arr_ptr = arr.as_mut_ptr() as *mut Vec<u8>; // pointer to 1st element
for i in 0..N {
arr_ptr.add(i).write(vec![]);
}
arr.into_inner()
};
for idx in 0..arr.len() {
println!("Index {}: {:?}", idx, arr[idx]);
}
} |
leonardo-m commentedSep 24, 2018
In this page:
https://doc.rust-lang.org/nightly/std/mem/union.MaybeUninit.html
I suggest to add an equivalent example of "how to safely initialize an array of Vecs" using MaybeUninit instead of uninitialized, if possible:
https://doc.rust-lang.org/nightly/std/mem/fn.uninitialized.html