Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 螺纹'&书信电报;main>';在创建大型数组时溢出了堆栈_Arrays_Rust_Stack Overflow - Fatal编程技术网

Arrays 螺纹'&书信电报;main>';在创建大型数组时溢出了堆栈

Arrays 螺纹'&书信电报;main>';在创建大型数组时溢出了堆栈,arrays,rust,stack-overflow,Arrays,Rust,Stack Overflow,staticvariableA_与A_相交从以下代码返回错误。 这段代码应该返回一个大的1356x1356二维数组bool use lazy_static::lazy_static; // 1.2.0 #[derive(Debug, Copy, Clone, Default)] pub struct A { pub field_a: [B; 2], pub ordinal: i32, } #[derive(Debug, Copy, Clone, Default)] pub s

static
variable
A_与A_相交
从以下代码返回错误。 这段代码应该返回一个大的1356x1356二维数组
bool

use lazy_static::lazy_static; // 1.2.0

#[derive(Debug, Copy, Clone, Default)]
pub struct A {
    pub field_a: [B; 2],
    pub ordinal: i32,
}

#[derive(Debug, Copy, Clone, Default)]
pub struct B {
    pub ordinal: i32,
}

pub const A_COUNT: i32 = 1356;

lazy_static! {
    pub static ref A_VALUES: [A; A_COUNT as usize] = { [A::default(); A_COUNT as usize] };

    pub static ref A_INTERSECTS_A: [[bool; A_COUNT as usize]; A_COUNT as usize] = {
        let mut result = [[false; A_COUNT as usize]; A_COUNT as usize];

        for item_one in A_VALUES.iter() {
            for item_two in A_VALUES.iter() {
                if item_one.field_a[0].ordinal == item_two.field_a[0].ordinal
                    || item_one.field_a[0].ordinal == item_two.field_a[1].ordinal
                    || item_one.field_a[1].ordinal == item_two.field_a[0].ordinal
                    || item_one.field_a[1].ordinal == item_two.field_a[1].ordinal
                {
                    result[item_one.ordinal as usize][item_two.ordinal as usize] = true;
                }
            }
        }
        result
    };
}

fn main() {
    A_INTERSECTS_A[1][1];
}
我见过有人通过在一个大列表中为结构实现
Drop
,来处理这个问题,但是我的列表中没有任何结构,您无法为bool实现它


如果我将
A\u INTERSECTS\u A:[[bool;A\u COUNT as usize];A\u COUNT as usize]
更改为
A\u INTERSECTS\u A:Box
代码工作正常,但是我真的想在这里使用一个数组。

这里的问题几乎肯定是当
A的初始化代码与
运行时,在堆栈上放置的巨大
结果
数组。它是13562&大约;1.8 MB,与堆栈大小具有相似的数量级。事实上,它比Windows默认的1MB大(我怀疑您是在Windows上,因为您收到了错误消息)

这里的解决方案是通过将堆栈移动到堆中来减小堆栈大小,例如,使用
Vec
(如您所示)或使用
。这将有一个额外的好处,即初始化代码不必从堆栈复制2MB到
a_与a
的内存(它只需要复制一些指针)

直接翻译为使用

pub static ref A_INTERSECTS_A: Box<[[bool; A_COUNT as usize]; A_COUNT as usize]> = {
    let mut result = Box::new([[false; A_COUNT as usize]; A_COUNT as usize]);
    // ...
}
let mut result = box [[false; A_COUNT as usize]; A_COUNT as usize];
如果您(非常明智地)喜欢坚持使用稳定的版本,那么在稳定之前的另一种选择是只使用
Vec
替换数组的外层:这保留了数组的所有数据局部性优点(所有内容都在内存中连续排列),尽管在静态知识方面稍微弱一些(编译器无法确定长度是否为1356)。由于
[\u;A\u COUNT]
未实现
克隆,因此无法使用
vec!`宏,因此(很遗憾)看起来如下:

pub static ref A_INTERSECTS_A: Vec<[bool; A_COUNT as usize]> = {
    let mut result =
        (0..A_COUNT as usize)
            .map(|_| [false; A_COUNT as usize])
            .collect::<Vec<_>>();
    // ...
}

我已经添加了一些显式类型,以便更清楚地了解其中的内容。这是因为
Vec
暴露到\u boxed\u slice
,因此我们可以使用
Box
(即动态长度)如果我们知道编译时的确切长度,则将其放入
框中。

是的,我尝试使用
Box::new
,但它不起作用。我不知道
Box
。谢谢,现在它有意义了。
pub static ref A_INTERSECTS_A: Box<[[bool; A_COUNT as usize]; A_COUNT as usize]> = {
    let mut result =
        (0..A_COUNT as usize)
            .map(|_| [false; A_COUNT as usize])
            .collect::<Vec<_>>();

    // ...

    // ensure the allocation is correctly sized
    let mut slice: Box<[[bool; A_COUNT as usize]]> = result.into_boxed_slice();
    // pointer to the start of the slices in memory
    let ptr: *mut [bool; A_COUNT as usize] = slice.as_mut_ptr();
    // stop `slice`'s destructor deallocating the memory
    mem::forget(slice);

    // `ptr` is actually a pointer to exactly A_COUNT of the arrays! 
    let new_ptr = ptr as *mut [[bool; A_COUNT as usize]; A_COUNT as usize];
    unsafe {
        // let this `Box` manage that memory
        Box::from_raw(new_ptr)
    }
}