스택큐힙리스트

C++는 최적화 컴파일러가 for-조건에서의 부수 효과를 무시할 수 있는지 허용합니까? 본문

카테고리 없음

C++는 최적화 컴파일러가 for-조건에서의 부수 효과를 무시할 수 있는지 허용합니까?

스택큐힙리스트 2023. 11. 27. 12:09
반응형

일부 레거시 코드를 디버깅하는 동안 기이한 (내게는) 컴파일러 동작을 발견했습니다. 이제 C++ 사양에 어떤 절이 다음과 같은 최적화를 허용하는지 알고 싶습니다. 여기서는 for-조건에서 함수 호출의 부작용이 무시되는 경우입니다:


void bar() 
{
extern int upper_bound;
upper_bound--;
}
void foo()
{
extern int upper_bound; // 다른 번역 단위에서 가져온 것으로 초기값은 대략 10입니다
for (int i = 0; i < upper_bound; ) {
bar();
}
}

결과적으로 어셈블리어에서 upper_bound가 레지스터에 유지되고 bar()에서의 upper_bound 감소가 영향을 미치지 않는 제어 경로가 있습니다.


제 컴파일러는 Microsoft Visual C++ 11.00.60610.1입니다.


솔직히 말해서, N3242의 6.5.3과 6.5.1에서는 많은 변동의 여지를 보이지 않지만, 놓치는 당연한 부분이 없는지 확실하게 하고 싶습니다.

답변 1

표준은 명확하고 모호하지 않게 두 개의 upper_bound 선언이 동일한 개체를 참조한다고 명시합니다.



3.5 프로그램 및 링크 [basic.link]


9 서로 다른 범위에서 선언되고 동일한 이름 (3절)을 가지는 두 개의 이름은 다음의 경우에 동일한 변수, 함수, 타입, 열거형, 템플릿 또는 이름공간을 나타내야 합니다.



  • 두 개의 이름이 외부 링크를 가지거나, 둘 다 내부 링크를 가지고 동일한 번역 단위에서 선언되는 경우; 그리고

  • 두 개의 이름이 동일한 이름공간의 멤버이거나, 동일한 클래스의 상속을 통하지 않는 멤버를 참조하는 경우; 그리고

  • 두 개의 이름이 함수를 나타내는 경우, 함수의 매개 변수 형식 목록(8.3.5)이 동일한 경우; 그리고

  • 두 개의 이름이 함수 템플릿을 나타내는 경우, 시그니처(14.5.6.1)가 동일한 경우입니다.


두 개의 이름 모두 외부 연결을 가지고 있습니다. 두 개의 이름 모두 전역 네임스페이스에 있는 멤버를 가리킵니다. 어느 이름도 함수나 함수 템플릿을 나타내지 않습니다. 따라서 두 개의 이름은 동일한 객체를 가리킵니다. 별개의 선언이 있기 때문에 이러한 기본적인 사실이 무효화된다는 주장은 마치 int i = 0; int &j = i; j = 1; return i;이 0을 반환할 수 있다고 말하는 것과 같습니다. 당연히 이는 1을 반환해야 합니다. 이것은 작동해야 하는 것입니다. 만약 그렇지 않다면, 컴파일러 버그를 발견한 것이죠.

답변 2

C++ 언어에서는 최적화 컴파일러가 for문의 조건에서 발생하는 부작용(side effects)을 무시할 수 있습니다. 최적화 컴파일러는 코드를 더 효율적으로 실행하도록 작성하는 도구인데, 이러한 도구는 프로그램의 실행 속도를 향상시키고 메모리 사용량을 줄이는 등의 최적화 작업을 진행하는 것을 목표로 합니다. 이를 위해 최적화 컴파일러는 코드를 분석하고 변환하여 더 효율적인 형태로 변환하는 작업을 수행합니다.
C++ 언어에서 for문의 조건에는 부작용이 발생할 수 있습니다. 부작용은 일반적으로 변수의 값 변경이나 함수 호출과 같은 작업을 의미합니다. 만약 최적화 컴파일러가 for문의 조건에서 발생하는 부작용을 무시한다면, 프로그램의 동작에 영향을 줄 수 있습니다. 따라서 최적화 컴파일러는 일반적으로 for문의 조건에서 발생하는 부작용을 무시하지 않고 그대로 실행하는 것이 일반적입니다.
한 가지 주의할 점은, 최적화 컴파일러는 제한된 범위에서만 부작용을 무시합니다. 예를 들어, for문의 조건에서 발생하는 부작용은 해당 for문의 실행 범위 내에서만 적용될 수 있으며, 다른 부분에서는 영향을 미치지 않을 수 있습니다. 이러한 제한 범위는 프로그래머가 의도한 동작과 다른 부수 효과를 방지하기 위한 것이며, 전반적인 프로그램의 안정성을 유지하는데 중요합니다.
최적화 컴파일러의 동작은 C++ 언어의 표준에 따라 다를 수 있으며, 여러 컴파일러 및 최적화 수준에 따라 차이가 있을 수 있습니다. 따라서 프로그래머는 가능한 모든 경우에 대해 부작용이 영향을 미치지 않는 것을 보장하기 위해 명시적으로 코드를 작성해야 합니다.
최적화 컴파일러가 for문의 조건을 무시하는 경우를 예로 들면, 다음과 같은 코드를 고려해보겠습니다.
```cpp
#include
int main() {
int i = 0;
for (; i < 10; ++i) {
std::cout << i << std::endl;
}
return 0;
}
```
위 코드에서는 for문의 조건에서 `i` 변수의 값을 변경하고 있습니다. 만약 최적화 컴파일러가 이 부작용을 무시한다면, for문은 멈추지 않고 무한히 반복될 수 있습니다. 이러한 문제를 방지하기 위해 최적화 컴파일러는 for문의 조건에서 발생하는 부작용을 무시하지 않고 적용하여 프로그램을 정상적으로 동작하도록 보장합니다.
종합하면, C++ 언어에서 최적화 컴파일러는 일반적으로 for문의 조건에서 발생하는 부작용을 무시하지 않고 실행합니다. 프로그래머는 부작용이 발생하는 부분에 대해 명확하게 코드를 작성하여 프로그램의 안전성과 정확성을 보장해야 합니다.

반응형
Comments