Does Box::new has any connection with stack memory?

It's expected that creating a large array on stack will lead to stack overflow. I.e.:
let r = [1_i64; 10000000]; // expected to get overflow

But it's not clear why creation of large array via Box::new should lead to stack overflow:
let mut r = Box::new([1_i64; 100000000]);

Seems, the point is we at first create the array on stack, then copy/move to heap, i.e. first is executed [1_i64; 100000000] leading to array creation in stack.

Well, Box::new is an ordinary function and ordinary functions take their arguments on the stack. The stack overflow is only avoided if the compiler can optimize it out.

One way to create a box without running into this issue is to first make a vector, then use Vec::into_boxed_slice to get a box. This will give you a Box<[i64]>, which you can turn into a Box<[i64; LEN]> via the TryFrom trait.

const LEN: usize = 1000000;
fn zeroed_box() -> Box<[i64; LEN]> {
    vec![0; LEN].into_boxed_slice().try_into().unwrap()
}

Godbolt confirms that the unwrap is optimized out

11 Likes