1

我试图了解可变大小的静态数组如何在内部工作:

以下是 C 中的一个固定大小的静态数组及其等效的程序集;

int main()
{
int arr[2] = {3};
}
================
main:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], 0
        mov     DWORD PTR [rbp-8], 2
        mov     eax, 0
        pop     rbp
        ret

然而,一个可变大小的数组如下所示

int main()
{
int varSize ;
int Arr[varSize];
}
=================
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     rax, rsp
        mov     rcx, rax
        mov     eax, DWORD PTR [rbp-4]
        movsx   rdx, eax
        sub     rdx, 1
        mov     QWORD PTR [rbp-16], rdx
        movsx   rdx, eax
        mov     r8, rdx
        mov     r9d, 0
        movsx   rdx, eax
        mov     rsi, rdx
        mov     edi, 0
        cdqe
        lea     rdx, [0+rax*4]
        mov     eax, 16
        sub     rax, 1
        add     rax, rdx
        mov     edi, 16
        mov     edx, 0
        div     rdi
        imul    rax, rax, 16
        sub     rsp, rax
        mov     rax, rsp
        add     rax, 3
        shr     rax, 2
        sal     rax, 2
        mov     QWORD PTR [rbp-24], rax
        mov     rsp, rcx
        mov     eax, 0
        leave
        ret

如果我声明一个可变大小的数组,我会看到很多汇编指令。有人可以解释这种可变大小的灵活性是如何实现的吗?

4

1 回答 1

1

与 - 通过减少堆栈指针分配内存的机制相同alloca(),假设堆栈足够大和/或操作系统将根据需要增长它。

当请求的大小超过内存页面并且堆栈接近其末尾时,可能会出现一些问题。通常,操作系统通过在堆栈顶部设置保护页面并监视该区域中的故障来增长堆栈,但这假设堆栈或多或少是按顺序增长的(通过推送和函数调用)。如果减少的堆栈指针超出保护页,它可能最终指向一个虚假的位置。我不确定编译器对这种可能性做了什么。

于 2020-06-21T14:05:58.647 回答