컴파일러는 컴파일 시 사이즈를 모르는 상태에서 어떻게 메모리를 할당합니까?
사용자로부터의 정수 입력, 즉 정수 배열의 크기를 받아들이는 C 프로그램을 작성하여 그 값을 사용하여 지정된 크기의 배열을 선언하고 배열 크기를 확인하여 확인하고 있습니다.
코드:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int n;
scanf("%d",&n);
int k[n];
printf("%ld",sizeof(k));
return 0;
}
놀랍게도 정답입니다!필요한 크기의 어레이를 작성할 수 있습니다.
, 및 시 값 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""n
컴파일러가 필요한 크기의 메모리를 할당할 수 있는 이유는 무엇입니까?
할 수 입니까?malloc()
★★★★★★★★★★★★★★★★★」calloc()
이것은, 「스태틱 메모리 할당」이 아닙니다. ★★★k
VLA ( Variable Length Array ) 、 VLA ( Variable Length Array ) 。크기는 다음 실행 시간 값에 따라 결정됩니다.n
.
에는 특정 메커니즘이 되어 있지 에서는 할당 메커니즘이 지정되어 있습니다.k
int *
실제 메모리 블록이 실행 시 스택에 할당되는 포인터.
VLA의 »sizeof
측정 시스템은 런타임에도 평가되므로 실험에서 측정 시스템에서 정확한 값을 얻을 수 있습니다. 쓰세요.%zu
)%ld
합니다.size_t
.
「 」의 malloc
( 할당) 메모리 malloc
할당되어 있는 명시적으로 까지, 는 「」, 「」는 「」로 할당 해제됩니다.free
메모리malloc
는, 블록의 마지막에 자동적으로 할당 해제되지 않습니다.
예시와 같이 VLA는 이 '범위 파괴' 기능을 제공하지 않습니다. ★★★k
는, 통상의 스코프 베이스의 라이프 타임 룰에 준거하고 있습니다.그 라이프 타임은 블록의 마지막에 종료됩니다.인 경우, 는 「」, 「」, 「VLA」, 「VLA」를 대체할 수 .malloc
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
'범위에서 필요 '', '어느 정도', '어느 정도', '어느 정도', '어느 정도', '어느 정도', '어느 정도', '어느 정도', '어느 정도', '어느 정도', '어느 정도 '어느 정도', '어느 정도', '어느 정도', '어느 정도',malloc
어레이를 VLA를 될 수 .malloc
VLA는 일반적으로 스택에 할당되며 오늘날까지 스택에 대용량 메모리 청크를 할당하는 것은 다소 의심스러운 프로그래밍 방식이라는 점에 유의하십시오.
가 VLA 배열은 컴파일러에 (VLA)를 사용할 malloc()
「메모리라고 것을 수 를 들어, 「스택 고유의 기능을 사용합니다.예를 들어 다음과 같은 시스템 고유의 기능을 사용합니다.alloca()
표준 C의 일부가 아닙니다.으로 사용 .malloc()
왜냐하면 최신 운영체제는 프로그램에 훨씬 적은 양의 스택메모리 할당량을 허용하기 때문입니다.
가변 길이 어레이의 메모리는 정적으로 할당할 수 없습니다.단, 스택에 할당할 수 있습니다.일반적으로 스택 포인터의 변경이 동적으로 결정되었을 때 함수 스택프레임의 위치를 추적하기 위해 "프레임 포인터"를 사용합니다.
프로그램을 컴파일하려고 하면 가변 길이 배열이 최적화되어 있는 것처럼 보입니다.컴파일러가 어레이를 할당하도록 코드를 수정했습니다.
#include <stdio.h>
int main(int argc, char const *argv[])
{
int n;
scanf("%d",&n);
int k[n];
printf("%s %ld",k,sizeof(k));
return 0;
}
gcc 6.3을 사용한 암용 Godbolt 컴파일(암 ASM을 읽을 수 있기 때문에 암을 사용)은 이것을 https://godbolt.org/g/5ZnHfa으로 컴파일합니다(내 것을 참조).
main:
push {fp, lr} ; Save fp and lr on the stack
add fp, sp, #4 ; Create a "frame pointer" so we know where
; our stack frame is even after applying a
; dynamic offset to the stack pointer.
sub sp, sp, #8 ; allocate 8 bytes on the stack (8 rather
; than 4 due to ABI alignment
; requirements)
sub r1, fp, #8 ; load r1 with a pointer to n
ldr r0, .L3 ; load pointer to format string for scanf
; into r0
bl scanf ; call scanf (arguments in r0 and r1)
ldr r2, [fp, #-8] ; load r2 with value of n
ldr r0, .L3+4 ; load pointer to format string for printf
; into r0
lsl r2, r2, #2 ; multiply n by 4
add r3, r2, #10 ; add 10 to n*4 (not sure why it used 10,
; 7 would seem sufficient)
bic r3, r3, #7 ; and clear the low bits so it is a
; multiple of 8 (stack alignment again)
sub sp, sp, r3 ; actually allocate the dynamic array on
; the stack
mov r1, sp ; store a pointer to the dynamic size array
; in r1
bl printf ; call printf (arguments in r0, r1 and r2)
mov r0, #0 ; set r0 to 0
sub sp, fp, #4 ; use the frame pointer to restore the
; stack pointer
pop {fp, lr} ; restore fp and lr
bx lr ; return to the caller (return value in r0)
.L3:
.word .LC0
.word .LC1
.LC0:
.ascii "%d\000"
.LC1:
.ascii "%s %ld\000"
이(' 배열VLA로되어 있습니다.이는 '가변장 배열'과 .alloca
정확히 어떤 컴파일러를 사용하느냐에 따라 다르지만 기본적으로는 크기를 계산하고 스택 포인터에서 전체 크기를 뺀 것입니다.
필요하죠.malloc
가 되다또한 표준 C++에서는 하지 않습니다.]
[1] "0까지 성장"하는 스택을 사용하는 일반적인 프로세서의 경우.
컴파일러가 컴파일 시에 변수를 위해 메모리를 할당한다고 하는 것은 컴파일러가 동작하는 동안 컴파일러가 사용할 수 있는 공간을 만드는 것이 아니라 컴파일러가 생성하는 실행 가능한 코드에 변수 배치가 결정되고 포함된다는 것을 의미합니다.실제 동적 메모리 할당은 생성된 프로그램이 실행될 때 실행됩니다.
언급URL : https://stackoverflow.com/questions/46387111/how-does-the-compiler-allocate-memory-without-knowing-the-size-at-compile-time
'source' 카테고리의 다른 글
HashMap과 TreeMap의 차이점은 무엇입니까? (0) | 2022.08.15 |
---|---|
VueJs를 사용하여 하위 구성 요소에서 개체 속성 변경 (0) | 2022.08.15 |
표준 라이브러리에서 피해야 할 기능은 무엇입니까? (0) | 2022.08.15 |
자바에서 사운드를 재생하려면 어떻게 해야 하나요? (0) | 2022.08.15 |
OkHttp를 사용하여 연결 시간 초과를 설정하는 방법 (0) | 2022.08.15 |