-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid use of mem::uninitialized #1
Comments
I tried using MaybeUninit initially; you can see me commenting out the feature attribute after giving up. |
Actually, I think I can make it work. But counter intuitively it's going to require more unsafe than otherwise. |
Hmmm... another roadblock run into, it's impossible to do the following: let mut rhs: [MaybeUninit<B>; N] = unsafe { mem::transmute::<[B; N], [MaybeUninit<B>; N]>(x) }; |
This issue is blocked on rust-lang/rust#61956 |
I poked at this last night, and I think pointer arithmetic provides a sound work-around: #[repr(transparent)]
pub struct Vector<T, const N: usize>([T; N]);
impl<T, const N: usize> Zero for Vector<T, {N}>
where
T: Zero,
{
fn zero() -> Self {
let mut origin = mem::MaybeUninit::<Vector<T, {N}>>::uninit();
let start: *mut T = unsafe { mem::transmute(&mut origin) };
for i in 0..N {
unsafe { start.offset(i as isize).write(<T as Zero>::zero()) }
}
unsafe { origin.assume_init() }
}
/* ... */
} My understanding is: although it is unsound to create an uninitialized value, it is nonetheless sound to create raw pointers to an uninitialized value (so long as we never dereference the pointer). I'm not an expert at this, though. Does this approach seem reasonable? |
@jswrenn Indeed, this approach is safe. Mutable pointers don't drop what they point to unless you call I think I would prefer something closer to: fn zero() -> Self {
let mut origin = mem::MaybeUninit::<Vector<T, {N}>>::uninit();
let mut start: *mut T = unsafe { mem::transmute(&mut origin) };
for _ in 0..N {
start = unsafe {
start.write(<T as Zero>::zero());
start.offset(1)
};
}
unsafe { origin.assume_init() }
} I'm surprised by the line: let start: *mut T = unsafe { mem::transmute(&mut origin) }; Didn't realize that was even possible. |
This issue has been fixed! Aljabar is now "safe" |
https://github.com/maplant/aljabar/blob/4c60bb838f2480b4a454703e7f1f278a1cc748c3/src/lib.rs#L224-L225
You should use
MaybeUninit
instead. Callingmem::uninitialized
is undefined behavior for uninhabited types like!
ofenum Void {}
. It is also undefined behavior forbool
, as the uninitialized content may have a different value than0
or1
, which are the only valid values for abool
. Alsomem::uninitialized
is deprecated in favor ofMaybeUninit
see docs.The text was updated successfully, but these errors were encountered: