하지만, 을 위의 설명과 일치하지 않으며, 부작용이 않는 함수에 __attribute__((__pure__))
을 첨부 할 경우 어떤 일이 일어날 수 있습니까?
정확히. 여기에 간단한 예제입니다 : GCC의
extern __attribute__((pure)) int mypure(const char *p);
int call_pure() {
int x = mypure("Hello");
int y = mypure("Hello");
return x + y;
}
내 버전 (4.8.4)는 (결과가 2*mypure()
입니다) mypure
에 두 번째 통화를 제거 할만큼 영리하다. mypure
이 printf
인 경우 상상해보십시오 - 인쇄 문자열 "Hello"
의 부작용이 사라집니다. 제가
char s[];
int call_pure() {
int x = mypure("Hello");
s[0] = 1;
int y = mypure("Hello");
return x + y;
}
call_pure
으로 교체하면 (s[0]
에 할당 mypure
의 출력 값을 변경할 수 있으므로) 모두 호출 출사되도록
는
참고.
은 함수가 당신이 원하는 것보다 적은 시간 를 호출 할 것을 단순히 가능성, 또는 정의되지 않은 동작 또는 심각한 문제의 다른 종류를 만들 수 있습니다?
음, 간접적으로 UB가 발생할 수 있습니다. 예 : 여기
extern __attribute__((pure)) int get_index();
char a[];
int i;
void foo() {
i = get_index(); // Returns -1
a[get_index()]; // Returns 0
}
컴파일러는 대부분 (기술적 언더 웰) get_index()
에 두 번째 전화를 삭제하고, 버퍼 오버 플로우가 발생할 것이다 -1
제 리턴 값을 사용한다.
하지만 글로벌 메모리에 액세스 않는 함수에 __attribute__((__const__))
을 첨부 할 경우 실제로 어떤 일이 일어날 수 있습니까?
하자 다시 mypure
이 __attribute__((const))
로 주석했다
int call_pure() {
int x = mypure("Hello");
s[0] = 1;
int y = mypure("Hello");
return x + y;
}
경우에 위의 예를 취할를, 컴파일러는 다시 두 번째 전화를 드롭 2*mypure(...)
에 수익을 최적화합니다. mypure
이 실제로 s
을 읽으면 잘못된 결과가 생성됩니다.
편집
난 당신이 손을 흔들며 방지하기 위해 요청하지만, 여기에 몇 가지 일반적인 설명은 알고있다. 기본적으로 함수 호출은 임의의 부작용 (전역 변수 수정 등)이있는 블랙 박스로 처리되어야하므로 컴파일러 내부에서 많은 최적화를 차단합니다. annotating function을 const 또는 pure 대신에 사용하면 컴파일러는 더 적극적인 최적화를 허용하는 표현식처럼 취급 할 수 있습니다.
예제가 너무 많아서 제공 할 수 없습니다. 위에서 주어진 것은 일반적인 서브 표현식 제거이지만 루프 불변 값, 데드 코드 제거, 앨리어스 분석 등의 이점을 쉽게 입증 할 수 있습니다.
컴파일러에 거짓말을하면 . –
@Jonathan Leffler는 Babbage가 묻는 질문이 잘못된 경우 "엔진"이 적절한 대답을 줄지 묻는 사람들에 대해 인용합니다. – Swift