How to allocate arrays on the heap in Rust 1.0?

The problem is that the array is being passed to the Box::new function as an argument, which means it has to be created first, which means it has to be created on the stack.

You're asking the compiler to create 8 megabytes of data on the stack: that's what's overflowing it.

The solution is to not use a fixed-size array at all, but a Vec. The simplest way I can think of to make a Vec of 8 million 10.0 is this:

fn main() {
    const SIZE: usize = 1024 * 1024;
    let v = vec![10.0; SIZE];
}

Or, if for some reason you'd rather use iterators:

use std::iter::repeat;

fn main() {
    const SIZE: usize = 1024 * 1024;
    let v: Vec<_> = repeat(10.0).take(SIZE).collect();
}

This should only perform a single heap allocation.

Note that you can subsequently take a Vec and turn it into a Box<[_]> by using the into_boxed_slice method.

See also:

  • Performance comparison of a Vec and a boxed slice

I ran into this too, and ended up first at Creating a fixed-size array on heap in Rust where you find the full answer.

The gist of the answer is this macro:

/// A macro similar to `vec![$elem; $size]` which returns a boxed array.
///
/// ```rustc
///     let _: Box<[u8; 1024]> = box_array![0; 1024];
/// ```
macro_rules! box_array {
    ($val:expr ; $len:expr) => {{
        // Use a generic function so that the pointer cast remains type-safe
        fn vec_to_boxed_array<T>(vec: Vec<T>) -> Box<[T; $len]> {
            let boxed_slice = vec.into_boxed_slice();

            let ptr = ::std::boxed::Box::into_raw(boxed_slice) as *mut [T; $len];

            unsafe { Box::from_raw(ptr) }
        }

        vec_to_boxed_array(vec![$val; $len])
    }};
}

which I like most, as it simply gives you what the OP wanted:

An array, and it works with stable rust.


The accepted answer is very unsatisfying as sometimes we do want arrays allocated on the heap to preserve the size information at the type level. Johannes's answer can now be slightly improved using const generics. Instead of a macro we can use a function like:

fn vec_to_boxed_array<T: Copy, const N: usize>(val: T) -> Box<[T; N]> {
    let boxed_slice = vec![val; N].into_boxed_slice();

    let ptr = Box::into_raw(boxed_slice) as *mut [T; N];

    unsafe { Box::from_raw(ptr) }
}