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

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 に答える