< 返回版块

facefaceless 发表于 2025-06-18 20:13

Tags:全局变量,LazyLock

我需要一个只读的全局数组,一开始我想用的是LazyLock<[i32; HUGE_SIZE]>,但是

static ARRAY: LazyLock<[i32; HUGE_SIZE]> = LazyLock::new(|| {
    let mut arr = [0; HUGE_SIZE];
    for (i, elem) in arr.iter_mut().enumerate() {
        *elem = i as i32;
    }
    arr
});

类似这样的代码会爆栈,或许我应该使用LazyLock<Box<[i32; HUGE_SIZE]>>? 或者说LazyLock里面再包一层指针才是合理的用法?

评论区

写评论
xiaoyaou 2025-06-19 15:27

因为LazyLock是调用闭包函数,先在栈上分配并初始化,然后再移动到目标位置的(LazyLock / Box)。所以改成 LazyLock<Box<[i32; HUGE_SIZE]>>是正确的,并且,需要先在堆上分配空间后,再初始化:

use std::sync::LazyLock;
const HUGE_SIZE: usize = 100000000;
static ARRAY: LazyLock<Box<[i32; HUGE_SIZE]>> = LazyLock::new(|| {
    let arr = Box::new_uninit();
    let mut arr: Box<[i32; HUGE_SIZE]> = unsafe { arr.assume_init() };
    for (i, e) in arr.iter_mut().enumerate() {
        *e = i as i32;
    }
    arr
});
fn main(){
    std::thread::sleep(std::time::Duration::from_secs(2))
}

或者是用上位老哥说的第三方库pinned_init替你做以上的初始化

Bai-Jinlin 2025-06-18 22:01

大数组的全局变量要套一层Box,不然就算可以通过编译,生成的可执行文件也会很大,初始化方面推荐用原地初始化的的pinned_init库。

use std::sync::LazyLock;
use pinned_init::{init_array_from_fn, InPlaceInit};
const HUGE_SIZE :usize= 1000000;
static ARRAY: LazyLock<Box<[usize; HUGE_SIZE]>> = LazyLock::new(|| {
    Box::init(init_array_from_fn(|i|i)).unwrap()
});
fn main(){
    assert_eq!(ARRAY[HUGE_SIZE-1],HUGE_SIZE-1);
}
1 共 2 条评论, 1 页