0

我对这个功能感到困惑。

int i;
for(i = 1; i<10; i++){
        int arr[i];
        printf("%d\n",sizeof(arr));
    }

return 0;

空间如何在有界(由 ESP)堆栈内存中增长?有没有一种编译技巧?

编辑解释:堆栈不应该是这样的吗?

0  ---> val of i uninitialized
-4 ---> arr[0] uninitialized

在第一个循环之后

0  ---> val of i uninitialized
-4 ---> arr[1] uninitialized
-8 ---> arr[0] uninitialized

我很想说:ESP 是否在循环的每次迭代下方移动?

4

3 回答 3

1

空间如何在有限大小的堆栈内存中增长?

你指的是空间char arr——它的空间不会增长。for它是循环范围内的局部变量。所以每次循环有一个新i的它都是一个全新的char arr.

于 2019-12-02T22:27:20.883 回答
0

有没有一种编译技巧?

是的,有点。它使用 VLA ( https://en.wikipedia.org/wiki/Variable-length_array )

Godbolt 对于检查这样的事情非常有用:

https://godbolt.org/z/_uR9Ac

如您所见,-Wvla确实为相关行触发了警告。

于 2019-12-02T22:45:58.577 回答
0

在每个循环中,都会为数组分配堆栈,然后释放。

有点不同的例子

#include "stdio.h"
#include "string.h"

int h(int x) 
{
    for(int i = 1; i<x; i++){
            char arr[i];
            memset(arr, i, sizeof(arr));
            printf("%d\n",sizeof(arr));
        }
    return 0;
}

int main()
{
   h(50);
}

在编译的代码中


.LC0:
        .string "%d\n"
h:
        push    rbp
        mov     rbp, rsp
        push    r13
        push    r12
        mov     r12d, edi
        push    rbx
        mov     ebx, 1
        push    rax
.L2:
        cmp     r12d, ebx
        jle     .L6
        lea     rax, [rbx+15]
        mov     r13, rsp
        mov     ecx, ebx
        mov     rsi, rbx
        and     rax, -16
        sub     rsp, rax
        mov     eax, ebx
        inc     rbx
        mov     rdi, rsp
        rep stosb
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        mov     rsp, r13
        jmp     .L2
.L6:
        lea     rsp, [rbp-24]
        xor     eax, eax
        pop     rbx
        pop     r12
        pop     r13
        pop     rbp
        ret
main:
        push    rax
        mov     edi, 50
        call    h
        xor     eax, eax
        pop     rdx
        ret

第 15,19 和 20 行分配空间,第 28 行为数组释放空间

https://godbolt.org/z/msgrc2

于 2019-12-02T22:46:39.877 回答