programing

alloca()는 메모리 레벨에서 어떻게 작동합니까?

stoneblock 2023. 6. 23. 21:42

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년대 후반으로 거슬러 올라갑니다.allocaVLA가 표준에 추가되기 전의 초기 비표준화 시도였습니다.

현재 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를 보았을 때 덤/예측 가능한 모드로 전환한 특별한 사례가 있을 수 있습니다. 컴파일러 공급업체가 그렇게 했는지 모르겠습니다.

allocaVLA의 가장 중요한 차이점은 장애 사례입니다.다음 코드:

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