앨리어싱(컴퓨팅)

Aliasing (computing)

컴퓨팅에서 앨리어싱메모리에 있는 데이터 위치가 프로그램의 서로 다른 상징적 이름을 통해 접속될 수 있는 상황을 설명한다. 따라서 하나의 이름을 통한 데이터 수정은 모든 별칭 이름과 관련된 값을 암시적으로 수정하며, 프로그래머는 이를 예상하지 못할 수도 있다. 결과적으로, 앨리어싱은 프로그램을 이해하고, 분석하고, 최적화하는 것을 특히 어렵게 만든다. 앨리어싱 분석기는 프로그램의 앨리어싱을 이해하는 데 유용한 정보를 만들고 계산하려고 한다.

버퍼 오버플로

예를 들어 대부분의 C 프로그래밍 언어 구현은 배열 경계 검사를 수행하지 않는다. 그런 다음 컴파일러와 컴퓨터 아키텍처의 조립 언어 규약에 의한 프로그래밍 언어의 구현을 이용하여 배열 외부에 글을 써서 앨리어싱 효과를 얻을 수 있다(완충 오버플로우의 일종). 이것은 C 언어 규격에 따라 정의되지 않은 행동을 유발하지만, C의 많은 구현은 여기에 설명된 앨리어싱 효과를 보여줄 것이다.

스택에 배열이 생성되면 해당 배열을 바로 옆에 메모리에 배열된 변수가 배열 외부에 인덱싱되고 관련 배열 요소를 변경하여 변수를 직접 변경할 수 있다. 예를 들어, 만약 어떤 것이 있다면... int 크기 2의 배열(이 예를 위해, 소위 말하는 것) arr), 옆에 int 가변적 (call it) i), arr[2] (즉, 세 번째 원소)는 다음과 같이 별칭이 된다. i 기억 속에 인접해 있다면

# 포함시키다 <stdio.h>  인트로 본래의() {   인트로 arr[2] = { 1, 2 };   인트로 i=10;    /* arr의 끝을 넘어서 쓰세요. 표준 C에서 정의되지 않은 동작은 일부 구현에서 i에 기록된다. */   arr[2] = 20;    활자화하다("nump 0: %d \t", arr[0]); // 출력 1   활자화하다("csv 1: %d \t", arr[1]); // 출력 2   활자화하다("csv 2: %d \t", arr[2]); // 앨리어싱이 발생한 경우 20 출력   활자화하다("i: %d \t\t", i); // 또한 앨리어싱 때문에 10이 아닌 20을 출력할 수 있지만, 컴파일러는 내가 레지스터에 저장되어 10을 인쇄했을 수 있다.   /* arr 사이즈는 여전히 2. */   활자화하다("arr 크기: %d \n", 의 크기(arr) / 의 크기(인트로)); } 

이는 배열은 연속 메모리의 블록이며 배열 요소는 단지 그 블록의 시작 주소를 단일 요소의 크기로 곱하여 상쇄함으로써 참조될 뿐이기 때문에 C의 일부 구현에서 가능하다. C에는 한계 확인이 없으므로 배열 외부에서 인덱싱 및 어드레싱이 가능하다. 앞서 언급한 앨리어싱 동작은 정의되지 않은 동작이라는 점에 유의하십시오. 예를 들어, 어떤 구현은 구조의 기본 단어 크기의 배수가 되는 메모리 위치에 변수를 정렬하기 위해 스택의 배열과 변수 사이에 공간을 남겨둘 수 있다. C 표준은 일반적으로 데이터를 메모리에 배치하는 방법을 명시하지 않는다. (ISO/IEC 9899:1999, 섹션 6.2.6.1).

컴파일러가 배열의 범위를 벗어나는 액세스에 대해 별칭 효과를 생략하는 것은 잘못되지 않는다.

앨리어스 포인터

또 다른 다양한 별칭은 둘 이상의 이름을 가진 기억 속의 한 위치를 언급할 수 있는 모든 언어에서 발생할 수 있다(예: 포인터 포함). 함수인 XOR 스왑 알고리즘의 C 를 참조하십시오. 이 알고리즘은 전달된 두 포인터가 구별된다고 가정하지만 실제로는 서로 동일하거나 별칭인 경우 함수가 실패한다. 이것은 포인터 인수를 수용하는 함수의 일반적인 문제로서, 특히 포인터에게 전달된 메모리 영역에서 복잡한 조작을 수행하는 함수의 경우 앨리어싱에 대한 허용 오차(또는 그 허용 오차)는 주의 깊게 문서화되어야 한다.

지정된 앨리어싱

제어된 앨리어싱 동작은 경우에 따라 바람직할 수 있다(즉, C의 메모리 레이아웃에 의해 활성화된 것과 달리 지정된 앨리어싱 동작). 포트란에서는 흔히 있는 일이다. 펄프로그래밍 언어는 다음과 같은 앨리어싱 동작을 일부 구성에서 지정한다. foreach 이것은 특정 데이터 구조를 더 적은 코드로 직접 수정할 수 있게 한다. 예를 들어,

나의 @array = (1, 2, 3);  앞을 내다 나의 달러화 (@array) {     # $element를 증가시켜 자동으로     # @array 수정, $201은 ''별칭''이기 때문에     # @array의 각 원소에 차례로.     달러화++; }  인쇄하다 "@array \n"; 

결과적으로 "2 3 4"를 출력할 것이다. 앨리어싱 효과를 우회하려면 인덱스 변수의 내용을 다른 것으로 복사하고 복사본을 변경할 수 있다.

최적화와의 충돌

최적기는 앨리어싱이 가능할 때 변수에 대해 보수적인 가정을 해야 하는 경우가 많다. 예를 들어, 변수의 값(예: x is 5) 일반적으로 특정 최적화(예: 지속적인 전파)를 허용한다. 그러나 컴파일러는 다른 변수(예: C)에 할당 후 이 정보를 사용할 수 없다. *y = 10그럴 수도 있기 때문이다. *y 의 가명이다. x. 이런 과제를 하고 나면 그럴 수도 있다. y = &x. 이 할당에 대한 효과로 *y, x의 값 또한 변경될 것이고, 그래서 정보를 전파할 것이다. x 다음 진술에 5이다. *y = 10 (만약에) 잠재적으로 틀릴 수 있다. *y 실로 의 가명이다. x그러나 포인터에 대한 정보가 있는 경우, 지속적인 전파 과정은 다음과 같은 쿼리를 만들 수 있다. x 의 가명이 되다 *y그렇다면, 답이 '아니오'라면 x = 5 안전하게 전파될 수 있다.

앨리어싱에 의해 영향을 받는 또 다른 최적화는 코드 순서 변경이다. 컴파일러가 결정하면 x 에 의해 별칭이 되지 않다 *y, 그런 다음 값을 사용하거나 변경하는 코드 x 할당 전에 이동할 수 있음 *y = 10이렇게 하면 스케줄링이 개선되거나 더 많은 루프 최적화가 수행될 수 있는 경우.

이러한 최적화를 예측 가능한 방식으로 활성화하기 위해 C 프로그래밍 언어ISO 표준(새 C99 버전 포함, 섹션 6.5, 단락 7 참조)은 다른 유형의 포인터를 사용하여 동일한 메모리 위치에 액세스하는 것이 불법(일부 예외사항 포함)임을 명시한다. 따라서 컴파일러는 그러한 포인터가 가명을 붙이지 않는다고 가정할 수 있다. 엄격한 앨리어싱 규칙으로 알려진 이 규칙은 때때로 성능의 인상적인 증가를 허용하지만,[1] 다른 유효한 코드를 깨는 것으로 알려져 있다. 몇몇 소프트웨어 프로젝트는 의도적으로 C99 표준의 이 부분을 위반한다. 예를 들어, Python 2.x참조 카운팅을 구현하기 위해 그렇게 했고,[2] 이러한 최적화를 가능하게 하기 위해 Python 3의 기본 객체 구조에 대한 변경을 요구하였다. 리눅스 커널은 엄격한 앨리어싱이 인라인 코드의 최적화에 문제를 일으키기 때문에 이렇게 한다.[3] 이 경우 gcc로 컴파일하면 옵션 -fno-strict-aliasing 예기치 않은 코드를 생성할 수 있는 원하지 않는 최적화를 방지하기 위해 호출된다.

하드웨어 앨리어싱

앨리어싱이라는 용어는 하드웨어 설계 선택 또는 하드웨어 고장으로 인해 메모리 선택 과정에서 하나 이상의 사용 가능한 주소 비트가 사용되지 않는 상황을 설명하는 데에도 사용된다.[4] 설치된 메모리 장치를 지원하는 데 필요한 것보다 더 많은 주소 비트를 사용할 수 있는 경우 이는 설계 결정일 수 있다. 고장이 발생하면 하나 이상의 주소 비트가 함께 단락되거나 접지(로직 0) 또는 공급 전압(로직 1)으로 강제 전환될 수 있다.

이 예에서는 메모리3 설계를 8개의 위치로 가정하고, 2 = 8 이후 3개의 주소 라인(또는 비트)만 요구한다고 가정한다. 주소 비트(이름 A2 ~ A0)는 표준 바이너리 카운터 방식으로 다음과 같이 고유한 메모리 위치를 선택하도록 디코딩된다.

A2 A1 A0 메모리 위치
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
1 0 0 4
1 0 1 5
1 1 0 6
1 1 1 7

위의 표에서 8개의 주소 비트의 고유한 조합 각각은 다른 메모리 위치를 선택한다. 그러나 하나의 주소 비트(A2)를 접지 측 단락시킬 경우 표는 다음과 같이 수정된다.

A2 A1 A0 메모리 위치
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3

이 경우 A2가 항상 0인 상태에서 처음 네 개의 메모리 위치가 중복되어 다시 두 번째 네 개로 나타난다. 메모리 위치 4부터 7까지 접근이 불가능해졌다.

이러한 변경이 다른 주소 비트로 발생하면 디코딩 결과는 다르지만, 일반적으로 효과는 동일하다: 단일 주소 비트의 손실이 사용 가능한 메모리 공간을 절반으로 줄이고 나머지 공간의 중복(별칭)을 초래한다.

참고 항목

참조

  1. ^ Mike Acton (2006-06-01). "Understanding Strict Aliasing".
  2. ^ Neil Schemenauer (2003-07-17). "ANSI strict aliasing and Python".
  3. ^ Linus Torvalds (2003-02-26). "Re: Invalid compilation without -fno-strict-aliasing".
  4. ^ Michael Barr (2012-07-27). "Software Based Memory Testing".

외부 링크