alloca()는 메모리 레벨에서 어떻게 작동합니까?
어떻게 해야 할지 생각 중입니다alloca()
실제로 메모리 레벨에서 작동합니다.리눅스 man 페이지에서:
alloca() 함수는 호출자의 스택 프레임에 공간 크기 바이트를 할당합니다.alloca()를 호출한 함수가 호출자에게 돌아오면 이 임시 공간이 자동으로 해제됩니다.
이것이 의미하는 것은alloca()
스택 포인터를 다음으로 전달합니다.n
바이트? 아니면 새로 생성된 메모리가 정확히 어디에 할당되어 있습니까?
그리고 이것은 가변 길이 배열과 정확히 동일하지 않습니까?
구현 세부 사항은 아마도 OS 등에 맡겨져 있을 것으로 알고 있습니다.하지만 저는 일반적으로 이것이 어떻게 이루어지는지 알고 싶습니다.
네.alloca
는 기능적으로 로컬 변수 길이 배열과 동일합니다. 즉, 다음과 같습니다.
int arr[n];
그리고 이것은:
int *arr = alloca(n * sizeof(int));
둘 다 공간 할당n
활자의 요소.int
겹겹이 쌓인사이의 유일한 차이점은arr
각각의 경우, 1) 하나는 실제 어레이이고 다른 하나는 어레이의 첫 번째 요소에 대한 포인터이며, 2) 어레이의 수명은 포함 범위로 끝나는 반면,alloca
메모리의 수명은 함수가 반환될 때 종료됩니다.두 경우 모두 어레이는 스택에 있습니다.
예를 들어, 다음 코드가 주어집니다.
#include <stdio.h>
#include <alloca.h>
void foo(int n)
{
int a[n];
int *b=alloca(n*sizeof(int));
int c[n];
printf("&a=%p, b=%p, &c=%p\n", (void *)a, (void *)b, (void *)c);
}
int main()
{
foo(5);
return 0;
}
이 기능을 실행하면 다음과 같은 메시지가 나타납니다.
&a=0x7ffc03af4370, b=0x7ffc03af4340, &c=0x7ffc03af4320
그 말은 기억이 다시 돌아왔다는 것을 보여줍니다.alloca
두 VLA의 메모리 사이에 위치합니다.
VLA는 C99에서 C 표준에 처음 등장했지만,alloca
그 훨씬 전에 주변에 있었습니다.리눅스 man 페이지에는 다음과 같은 내용이 있습니다.
에 부합하는
이 기능은 POSIX.1-2001에는 없습니다.
alloca() 함수가 32V, PWB, PWB.2, 3BSD 및 4BSD에서 나타났다는 증거가 있습니다.4.3에는 그것에 대한 man 페이지가 있습니다.BSD. Linux는 GNU 버전을 사용합니다.
BSD 3는 70년대 후반으로 거슬러 올라갑니다.alloca
VLA가 표준에 추가되기 전의 초기 비표준화 시도였습니다.
현재 VLA를 지원하지 않는 컴파일러(예: MSVC)를 사용하지 않는 한 VLA는 이제 동일한 기능을 얻기 위한 표준화된 방법이기 때문에 이 기능을 사용할 이유가 없습니다.
다른 답변은 VLA의 역학을 정확하게 설명하고 있습니다.alloca()
.
그러나, 다음 사이에는 상당한 기능적 차이가 있습니다.alloca()
자동 VLA를 사용할 수 있습니다.개체의 수명입니다.
의 alloca()
수명은 함수가 반환될 때 종료됩니다.VLA의 경우 포함 블록이 종료되면 개체가 해제됩니다.
char *a;
int n = 10;
{
char A[n];
a = A;
}
// a is no longer valid
{
a = alloca(n);
}
// is still valid
따라서 VLA를 사용할 수 없는 동안 루프의 스택을 쉽게 소진할 수 있습니다.
for (...) {
char *x = alloca(1000);
// x is leaking with each iteration consuming stack
}
대
for (...) {
int n = 1000;
char x[n];
// x is released
}
alloca는 구문 관점에서 함수처럼 보이지만 현대 프로그래밍 환경에서는 일반 함수로 구현될 수 없습니다*.함수와 유사한 인터페이스를 가진 컴파일러 기능으로 간주해야 합니다.
전통적으로 C 컴파일러는 "스택 포인터"와 "프레임 포인터"(또는 베이스 포인터)라는 두 개의 포인터 레지스터를 유지했습니다.스택 포인터는 스택의 현재 범위를 구분합니다.프레임 포인터는 함수에 대한 항목에 스택 포인터의 값을 저장하고 로컬 변수에 액세스하고 함수 종료 시 스택 포인터를 복원하는 데 사용됩니다.
오늘날 대부분의 컴파일러는 기본적으로 일반 함수에서 프레임 포인터를 사용하지 않습니다.현대의 디버그/예외 정보 형식은 이를 불안정하게 만들었지만, 여전히 이 정보가 무엇인지 이해하고 필요한 곳에 사용할 수 있습니다.
특히 프레임 포인터를 사용하는 alloca 또는 가변 길이 배열이 있는 함수의 경우 함수가 스택 프레임의 위치를 추적하는 동시에 가변 길이 배열을 수용하도록 스택 포인터를 동적으로 수정할 수 있습니다.
예를 들어, 나는 O1에서 팔을 위한 다음 코드를 만들었습니다.
#include <alloca.h>
int bar(void * baz);
void foo(int a) {
bar(alloca(a));
}
그리고 (내 것을) 받았습니다.
foo(int):
push {fp, lr} @ save existing link register and frame pointer
add fp, sp, #4 @ establish frame pointer for this function
add r0, r0, #7 @ add 7 to a ...
bic r0, r0, #7 @ ... and clear the bottom 3 bits, thus rounding a up to the next multiple of 8 for stack alignment
sub sp, sp, r0 @ allocate the space on the stack
mov r0, sp @ make r0 point to the newly allocated space
bl bar @ call bar with the allocated space
sub sp, fp, #4 @ restore stack pointer and frame pointer
pop {fp, pc} @ restore frame pointer to value at function entry and return.
또한 yes alloca와 가변 길이 배열은 매우 유사합니다(다른 답변에서 정확히 동일하지는 않음을 지적함).alloca는 두 개의 구성 요소 중 더 오래된 것으로 보입니다.
충분히 덤/예측 가능한 컴파일러를 사용하면 어셈블러에서 alloca를 함수로 구현할 수 있습니다.특히 컴파일러는 필요합니다.
- 모든 함수에 대한 프레임 포인터를 일관되게 만듭니다.
- 로컬 변수를 참조하려면 스택 포인터 대신 프레임 포인터를 일관되게 사용합니다.
- 함수 호출에 대한 매개 변수를 설정할 때 프레임 포인터 대신 스택 포인터를 일관되게 사용합니다.
이것은 분명히 처음 구현된 방법입니다(https://www.tuhs.org/cgi-bin/utree.pl?file=32V/usr/src/libc/sys/alloca.s ).
실제 구현을 어셈블리 기능으로 사용할 수도 있지만, 컴파일러에서 alloca를 보았을 때 덤/예측 가능한 모드로 전환한 특별한 사례가 있을 수 있습니다. 컴파일러 공급업체가 그렇게 했는지 모르겠습니다.
alloca와 VLA의 가장 중요한 차이점은 장애 사례입니다.다음 코드:
int f(int n) {
int array[n];
return array == 0;
}
int g(int n) {
int *array = alloca(n);
return array == 0;
}
VLA는 할당 실패를 감지할 가능성이 없습니다. 이는 언어 구조에 부과하기에는 매우 비C적인 것입니다.따라서 Alloca()는 훨씬 더 잘 설계되었습니다.
언급URL : https://stackoverflow.com/questions/69406966/how-does-alloca-work-on-a-memory-level
'programing' 카테고리의 다른 글
C#에 저장된 프로시저에서 반환 값을 가져오는 중 (0) | 2023.06.23 |
---|---|
@EnableJpa* 주석을 사용한 Spring @WebMvcTest (0) | 2023.06.23 |
잭슨이 변수 이름의 대소문자를 변경하지 못하도록 합니다. (0) | 2023.06.23 |
Excel 스프레드시트에서 장고 모델로 데이터 가져오기 (0) | 2023.06.23 |
mysqladmin을 사용하여 데이터베이스 문자 집합을 설정하는 데 문제가 발생했습니다. (0) | 2023.06.23 |