programing

GCC는 가변 길이 배열을 어떻게 구현합니까?

stoneblock 2023. 10. 21. 09:52

GCC는 가변 길이 배열을 어떻게 구현합니까?

GCC는 VLA(Variable-length Arrays)를 어떻게 구현합니까?이러한 어레이는 기본적으로 alloca에 의해 반환되는 것과 같이 동적으로 할당된 스토리지에 대한 포인터입니까?

제가 생각할 수 있는 또 다른 대안은 그러한 배열이 함수의 마지막 변수로 할당되어 컴파일 시간 동안 변수의 오프셋을 알 수 있다는 것입니다.그러나 두 번째 VLA의 오프셋은 컴파일 시간 동안 다시 알 수 없습니다.

다음은 VLA 지원을 위해 일부 GCC 문서에서 가져온 다음 예제 라인에 대한 할당 코드(x86 - x64 코드가 유사함)입니다.

char str[strlen (s1) + strlen (s2) + 1];

에 대한 계산이 어디에strlen (s1) + strlen (s2) + 1eax(GCC MinGW 4.8.1 - 최적화 없음):

mov edx, eax
sub edx, 1
mov DWORD PTR [ebp-12], edx
mov edx, 16
sub edx, 1
add eax, edx
mov ecx, 16
mov edx, 0
div ecx
imul    eax, eax, 16
call    ___chkstk_ms
sub esp, eax
lea eax, [esp+8]
add eax, 0
mov DWORD PTR [ebp-16], eax

그래서 본질적으로 그들이alloca().

음, 이것들은 VLA 주변의 제한에 근거해서 어둠 속에서 약간의 거친 칼부림일 뿐입니다. 하지만 어쨌든:

VLA는 다음과 같을 수 없습니다.

  • 외전의
  • 구성원들
  • 정적인
  • 지정되지 않은 경계로 선언됨(함수 프로토타입에 대해 저장)

이 모든 것은 VLA가 힙이 아닌 스택에 할당되고 있음을 나타냅니다.예, VLA는 새 블록이 할당될 때마다 할당되는 마지막 스택 메모리 청크일 것입니다(블록 범위에서와 같은 블록, 루프, 함수, 분기 또는 기타).
그래서 VLA가 스택 오버플로의 위험을 크게 높이는 이유이기도 합니다(예: 재귀적 함수 호출과 함께 VLA를 사용할 생각은 하지 마십시오!).
이것은 또한 아웃오브바운드 액세스가 문제를 일으킬 가능성이 매우 높은 이유이기도 합니다. 블록이 끝나면 Was VLA 메모리를 가리키는 모든 것이 잘못된 메모리를 가리키게 됩니다.
하지만 이점은 이 어레이가 스레드 안전성을 확보하는 이유와 힙 메모리에 비해 더 빠른 이유입니다.

VLA의 크기는 다음과 같을 수 없습니다.

  • 가.extern가치
  • 0 또는 0

외부의 제약은 아주 명백하고, 0이 아닌 것도 부정적이지 않은 것과 마찬가지로...그러나: 예를 들어 VLA의 크기를 지정하는 변수가 signed int인 경우 컴파일러는 오류를 발생시키지 않습니다. 즉, VLA의 평가 및 할당은 컴파일 시간이 아닌 런타임 중에 수행됩니다.따라서 컴파일 시간 동안 VLA의 크기가 주어질 수도 없고 주어질 필요도 없습니다.
Michael Burr가 정확히 지적했듯이, VLA의 것들은 다음과 매우 비슷합니다.alloca메모리, 하나의 IMHO와 함께, 결정적인 구별: 할당된 메모리alloca는 할당 시점부터 그리고 나머지 함수 전체에 걸쳐 유효합니다.VLA는 블록 범위이므로 VLA가 사용되는 블록을 벗어나면 메모리가 해제됩니다.

void alloca_diff( void )
{
    char *alloca_c, *vla_c;
    for (int i=1;i<10;++i)
    {
        char *alloca_mem = alloca(i*sizeof(*alloca_mem));
        alloca_c = alloca_mem;//valid
        char vla_arr[i];
        vla_c = vla_arr;//invalid
    }//end of scope, VLA memory is freed
    printf("alloca: %c\n", *alloca_c);//fine
    printf("vla: %c\n\", *vla_c);//undefined behaviour... avoid!
}//end of function alloca memory is freed, irrespective of block scope

언급URL : https://stackoverflow.com/questions/21182307/how-does-gcc-implement-variable-length-arrays