문제

가변 길이 배열을 사용하는 오버 헤드가 있습니까? 런타임에 명령 줄 인수를 통해 배열의 크기를 전달할 수 있습니까? 배열을 자동 및 동적으로 할당하는 것과 비교하여 왜 도입됩니까?

도움이 되었습니까?

해결책

VLA에는 약간의 오버 헤드가 있습니다 ( "일반"이라는 이름의 컴파일 타임 크기 배열과 비교).

첫째, 런타임 길이는 있지만 언어는 런타임에 배열의 실제 크기를 얻을 수있는 수단을 제공합니다 (사용 sizeof). 이것은 즉시 배열의 실제 크기가 어딘가에 저장되어야 함을 의미합니다. 이로 인해 어릴 적 메모리 별 메모리 오버 헤드가 발생합니다. 그러나 VLA는 자동 객체로만 선언 될 수 있으므로이 메모리 오버 헤드는 누구나 눈치 채지 못하는 것이 아닙니다. 그것은 통합 유형의 추가 로컬 변수를 선언하는 것과 같습니다.

둘째, VLA는 일반적으로 스택에 할당되지만 변수 크기 때문에 일반적으로 메모리의 정확한 위치는 컴파일 시간에 알려지지 않습니다. 이러한 이유로 기본 구현은 일반적으로 메모리 블록에 대한 포인터로 구현해야합니다. 이것은 몇 가지 추가 메모리 오버 헤드 (포인터의 경우)를 소개하며, 이는 위에서 설명한 이유에 대해 다시 미미합니다. 실제 배열을 찾기 위해 포인터 값을 읽어야하기 때문에 약간의 성능 오버 헤드도 소개합니다. 이것은 액세스 할 때 얻는 것과 같은 오버 헤드입니다 malloc-ED 어레이 (그리고 이름이 지정된 컴파일 타임 크기의 배열로 얻지 못함).

VLA의 크기는 런타임 정수 값이므로 물론 명령 줄 인수로 전달 될 수 있습니다. VLA는 크기가 어디에서 오는지 신경 쓰지 않습니다.

VLA는 할당/거래 비용이 낮은 런타임 크기의 배열로 도입되었습니다. "일반"이름이 지정된 컴파일 타임 크기의 배열 (거의 할당 할당 비용이 거의 없지만 고정 된 크기) 사이에 적합합니다. malloc-ED 어레이 (런 타임 크기가 있지만 비교적 높은 할당 량으로 할당 비용).

VLA는 자동 (거의] 자동 (예 : 로컬) 객체와 동일한 범위 의존적 수명 규칙을 준수합니다. 이는 일반적으로 교체 할 수 없음을 의미합니다. malloc-ED 어레이. 적용 가능성은 일반적인 자동 수명이있는 빠른 런 타임 크기의 배열이 필요한 상황으로 제한됩니다.

다른 팁

가변 길이 배열로 런타임 오버 헤드가 있지만 측정하기 위해 상당히 어려워 야합니다. 주목하십시오 sizeof(vla) 컴파일 타임 상수가 아닙니다 vla 가변 길이 배열입니다.

배열의 크기는 런타임에 함수로 전달 될 수 있습니다. 명령 줄 인수에서 크기를 가져 와서 정수로 변환하고 런타임에 기능으로 전달하면 작동합니다.

변수가 올바른 크기에 자동으로 할당되고 함수에서 종료시 자동으로 해제되므로 가변 길이 배열이 사용됩니다. 이렇게하면 공간을 과도하게 할당하는 공간을 피하고 (대부분 최소 크기로 작업 할 때 가능한 최대 크기를위한 충분한 공간을 할당하고) 메모리 정리 문제를 피합니다.

또한 다차원 배열을 사용하면 Afaik Fortran과 비슷하게 작동합니다. 배열의 주요 차원을 제외하고 고정 된 크기로 고정되지 않고 모든 치수를 동적으로 구성 할 수 있습니다.


VLA에 대한 일부 런 타임 오버 헤드의 구체적인 증거 - 적어도 SPARC의 GCC 4.4.2 (Solaris 10).

아래 두 파일을 고려하십시오.

VLA.C- 가변 길이 배열 사용

#include <assert.h>
#include <stddef.h>
extern size_t identity_matrix(int n, int m);

size_t identity_matrix(int n, int m)
{
    int vla[n][m];
    int i, j;
    assert(n > 0 && n <= 32);
    assert(m > 0 && m <= 32);
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            vla[i][j] = 0;
        }
        vla[i][i] = 1;
    }
    return(sizeof(vla));
}

FLA.C- 고정 길이 배열 사용

#include <assert.h>
#include <stddef.h>
extern size_t identity_matrix(int n, int m);

size_t identity_matrix(int n, int m)
{
    int fla[32][32];
    int i, j;
    assert(n > 0 && n <= 32);
    assert(m > 0 && m <= 32);
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            fla[i][j] = 0;
        }
        fla[i][i] = 1;
    }
    return(sizeof(fla));
}

컴파일 및 객체 파일 크기

비교 목적으로 로컬 어레이의 이름은 다릅니다 (vla vs fla), 배열의 치수는 선언 될 때 다릅니다. 그렇지 않으면 파일이 동일합니다.

나는 다음을 사용하여 컴파일했다 :

$ gcc -O2 -c -std=c99 fla.c vla.c

객체 파일 크기는 'ls'와 'size'로 측정 한대로 다소 다릅니다.

$ ls -l fla.o vla.o
-rw-r--r--   1 jleffler rd          1036 Jan  9 12:13 fla.o
-rw-r--r--   1 jleffler rd          1176 Jan  9 12:13 vla.o
$ size fla.o vla.o
fla.o: 530 + 0 + 0 = 530
vla.o: 670 + 0 + 0 = 670

오버 헤드가 얼마나 고정되어 있는지와 가변의 양을 확인하기 위해 광범위한 테스트를 수행하지 않았지만 VLA를 사용하는 데 오버 헤드가 있습니다.

가변 길이 배열을 사용하는 오버 헤드가 있는지 궁금합니다.

아니요

런타임에 명령 줄 인수를 통해 배열의 크기를 전달할 수 있습니까?

예.

배열을 자동 및 동적으로 할당하는 것과 비교하여 왜 도입됩니까?

자동 할당은 컴파일 시간에 알려진 고정 크기 만 허용합니다.

동적으로 할당 (malloc) 배열을 보관합니다 더미, 메모리 공간이 넓지 만 액세스가 느리다.

VLA는 배열을 배치하여 작동합니다 스택. 이렇게하면 할당과 액세스가 매우 빠릅니다. 하지만 스택은 일반적으로 (몇 kb의) 작고, VLA가 스택을 넘치면 무한 재귀와 구별 할 수 없습니다.

VLA에 대한 오버 헤드가 거의 없어야합니다 (최대 스택 포인터에 추가해야 함). 동적 할당에는 수동 메모리 관리가 필요하며 VLA의 스택 기반 할당보다 느리게 진행되며 배열의 "자동"선언은 배열 크기에 대한 컴파일 타임 표현식이 필요합니다. 그러나 스택 오버플로가 발생하면 정의되지 않은 동작이 발생하므로 VLA를 비교적 작게 유지하십시오.

명령 줄 인수를 통해 배열의 크기를 전달할 수 있지만, 직접 처리하려면 코드를 작성해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top