Box::new 爆栈了,并不是我想的那样QwQ

275 阅读1分钟

下面这段代码会爆栈:

const SIZE: usize = 64 * 4096;

fn main() {
    let _boxed_big_arr = Box::new([0_i128; SIZE]);
}

哎?Box 不是分配到了堆上吗??

再仔细看看文档里面说的:

alloc::boxed::Box
pub fn new(x: T) -> Self

Allocates memory on the heap and then places x into it. This doesn't actually allocate if T is zero-sized.

也就是说,在将这个巨型数组放到堆上之前,需要在栈上先创建这个数组,之后才会将这个数组移动到堆上

整点汇编 (结果由 godbolt.org/ 生成)

example::main:
        mov     eax, 4194344
        call    __rust_probestack /* 这里是用堆栈探针进行检测,防止爆栈,
                                     实际上我们的函数在这里就被停下了,但我们主要看的是 
                                     Box::new 先在栈上分配内存这一点,如果想要详细了解,可以参考下文 */
        sub     rsp, rax
        lea     rdi, [rsp + 24]
        xor     esi, esi
        mov     edx, 4194304 /* 哇,"豪"无人性 */
        mov     qword ptr [rsp], rdx /* 栈上遭殃了趴,应该是这样的趴... */
        mov     rax, qword ptr [rip + memset@GOTPCREL]
        call    rax
        mov     rdi, qword ptr [rsp]
        mov     esi, 8
        call    alloc::alloc::exchange_malloc /* 看个大概,不深究了 QwQ */

有关__rust_probestack 看不到具体实现,因为底层是调用的 C