#Uninit Box

33 messages · Page 1 of 1 (latest)

proud pumice
#

Is there any way to get Box<T> where T is not initialized without storing T on the stack first?

finite pelican
dusky acorn
finite pelican
#

Huh. Seems like the unstable method is likely to be stable in the version after next (1.82). It just finished FCP.

proud pumice
#
pub unsafe fn uninit_box<T>() -> Box<T> {
    let layout = Layout::new::<T>();
    let ptr = alloc(layout) as *mut T;
    if ptr.is_null() {
        handle_alloc_error(layout);
    }
    Box::from_raw(ptr)
}```

Aside from T being uninitialized, is there any other safety concern? (asking because I'm not sure if this deallocates)
dusky acorn
#

that's a pretty huge "aside"

proud pumice
#

I know, that's why I marked the fn as unsafe, but I meant if there are other issues I'm oblivious to

dusky acorn
#

it being uninitialized is a much bigger problem than you seem to think

#

you are not handling zero sized types correctly

#

it's also insta ub if you call it for types like u8 for example

#

anything that needs initializing

#

the ub happens inside the function, not in whatever the caller does with it next

#

that is because it's UB to have uninitialized values, not just when you use them

dense current
#

if you don't want to switch to nightly, you could just copy what std is doing

proud pumice
#

thanks, I might also give a deeper look to the unsafe docs

finite pelican
# proud pumice thanks, I might also give a deeper look to the unsafe docs
use std::alloc::{alloc, Layout};
use std::mem::MaybeUninit;
use std::ptr::NonNull;

pub fn uninit_box<T>() -> Box<MaybeUninit<T>> {
    unsafe {
        Box::from_raw(if size_of::<T>() == 0 {
            NonNull::dangling().as_ptr()
        } else {
            let layout = Layout::new::<T>();
            let ptr = alloc(layout).cast::<MaybeUninit<T>>();
            if ptr.is_null() {
                panic!("allocation failed");
            }
            ptr
        })
    }
}
lyric isle
#

you can also just.. Box::new(MaybeUninit::uninit())

lyric isle
rose finch
#

?eval Box::new(std::mem::MaybeUninit::<[i128; 10000000]>::uninit())

velvet lionBOT
#
thread 'main' has overflowed its stack
fatal runtime error: stack overflow```
dense current
#

because the compiler is allowed to read the value at any point (even if it probably won't)

dusky acorn
#

its kinda undecided what happens if there's indirection

latent robin
#

?eval ```rust
Vec::<i128>::with_capacity(10000000)

velvet lionBOT
#
[]```
dense current
#

so using Vec is correct, but against the spirit ;)

latent robin
#

I don't mean using Vec, but seeing how with_capacity allocates (it seems to use the allocator directly) without exploding the stack might be useful.