【问题标题】:How to allocate arrays on the heap in Rust 1.0?Rust 1.0 如何在堆上分配数组?
【发布时间】:2015-07-26 09:22:15
【问题描述】:

已经有一个 question 用于此,但与 Rust 0.13 相关,并且语法似乎已经改变。从当前的documentation 我了解到在堆上创建一个数组是这样的:

fn main() {
    const SIZE: usize = 1024 * 1024;
    Box::new([10.0; SIZE]);
}

但是当我运行这个程序时,我得到了以下错误:

thread '<main>' has overflowed its stack

我做错了什么?

【问题讨论】:

    标签: arrays rust heap-memory


    【解决方案1】:

    接受的答案非常不令人满意,因为有时我们确实希望在堆上分配数组以保留类型级别的大小信息。 Johannes 的答案现在可以使用 const 泛型稍微改进。我们可以使用如下函数来代替宏:

    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) }
    }
    

    【讨论】:

      【解决方案2】:

      我也遇到了这个问题,最后在Creating a fixed-size array on heap in Rust 找到了完整的答案。

      答案的要点是这个宏:

      /// 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])
          }};
      }
      

      这是我最喜欢的,因为它只是为您提供了 OP 想要的东西:

      一个数组,它适用于稳定的 rust。

      【讨论】:

        【解决方案3】:

        问题是数组作为参数传递给Box::new函数,这意味着它必须首先创建,这意味着它必须在上创建堆栈

        您要求编译器在堆栈上创建 8 MB 的数据:这就是溢出的原因。

        解决方案是根本不使用固定大小的数组,而是使用Vec。我能想到的制作 800 万 10.0Vec 的最简单方法是:

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

        或者,如果出于某种原因您更愿意使用迭代器:

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

        应该只执行一次堆分配。

        请注意,您随后可以使用into_boxed_slice 方法将Vec 转换为Box&lt;[_]&gt;

        另见:

        【讨论】:

        • 请注意,box 语法应该对此有所帮助,但它现在不稳定,我不确定它是否支持直接堆放置数组。
        • 你应该可以使用vec![10.0; 1024 * 1024]
        猜你喜欢
        • 2021-05-31
        • 1970-01-01
        • 2016-03-27
        • 2020-10-03
        • 1970-01-01
        • 2019-01-09
        • 2023-03-27
        • 2019-05-10
        • 2021-03-14
        相关资源
        最近更新 更多