我正在用 Rust 创建国际象棋换位表。为此,我创建了一个
TranspositonEntry
,它记录了一个 u64,它表示一个位置的哈希值和一个实际上只是一个 u16 的移动。我想将 2^19 个条目存储到一个数组中。然而,有一个问题。该数组导致堆栈溢出。
我认为数组的大小(以字节为单位)为 10 * 2^19,或者刚刚超过 5 MB,这不会导致堆栈溢出。但是,我认为这是不正确的,因为我无法修复代码以免导致堆栈溢出。
一个小例子是
struct Move {
val : u16
}
impl Move {
const NULL : Self = Self {val : 0};
}
struct TranspositionEntry {
mov : Move,
hash : u64
}
impl TranspositionEntry {
const NULL_ENTRY: Self = Self { mov : Move::NULL, hash : 0};
}
fn main() {
let table = [TranspositionEntry::NULL_ENTRY; 524288];
}
我认为表不应该大到足以导致堆栈溢出,但它确实如此。
默认堆栈大小比您想象的要小。在 Windows 上,默认情况下堆栈大小仅为 1 MiB。在 Linux 上,它通常为 8 MiB,您可以这样检查:
$ ulimit -s
8192
当您生成线程时,您可以指定不同的堆栈大小:
use std::thread;
fn main() {
let builder = thread::Builder::new().stack_size(32 * 1024); // 32 MiB
let handler = builder.spawn(|| {
// this should work now
let table = [TranspositionEntry::NULL_ENTRY; 524288];
}).unwrap();
handler.join().unwrap();
}
但在这种情况下,更好的解决方案是在堆上分配表。
fn main() {
let table = vec![TranspositionEntry::NULL_ENTRY; 524288];
}