developer tip

온라인 IDE에서 이상하게 작동하는 프로그램

copycodes 2020. 10. 14. 07:57
반응형

온라인 IDE에서 이상하게 작동하는 프로그램


아래 C ++ 프로그램 ( 소스 )을 보았습니다 .

#include <iostream>
int main()
{
    for (int i = 0; i < 300; i++)
        std::cout << i << " " << i * 12345678 << std::endl;
}

간단한 프로그램처럼 보이며 로컬 컴퓨터에 다음과 같은 올바른 출력을 제공합니다.

0 0
1 12345678
2 24691356
...
297 -628300930
298 -615955252
299 -603609574

그러나 codechef 와 같은 온라인 IDE 에서는 다음과 같은 출력을 제공합니다.

0 0
1 12345678
2 24691356
...
4167 -95167326
4168 -82821648
4169 -7047597

for루프가 300에서 종료 되지 않는 이유는 무엇 입니까? 또한이 프로그램은 항상에서 종료됩니다 4169. 4169다른 가치가 아닌가?


온라인 컴파일러는 GCC 또는 호환 컴파일러를 사용한다고 가정하겠습니다. 물론 다른 컴파일러도 동일한 최적화를 수행 할 수 있지만 GCC 문서에서는 수행하는 작업을 잘 설명합니다.

-faggressive-loop-optimizations

이 옵션은 루프 최적화 프로그램에 언어 제약 조건을 사용하여 루프 반복 횟수에 대한 경계를 파생하도록 지시합니다. 예를 들어 부호있는 정수 오버플로 또는 범위를 벗어난 배열 액세스를 유발하여 루프 코드가 정의되지 않은 동작을 호출하지 않는다고 가정합니다. 루프 반복 횟수에 대한 경계는 루프 풀기 및 필링 및 루프 종료 테스트 최적화를 안내하는 데 사용됩니다. 이 옵션은 기본적으로 활성화되어 있습니다.

이 옵션은 단지 UB가 입증 된 경우를 기반으로 가정을 허용합니다. 이러한 가정을 활용하려면 상수 접기와 같은 다른 최적화를 활성화해야 할 수 있습니다.


부호있는 정수 오버플로에 정의되지 않은 동작이 있습니다. 옵티마이 저는 i173보다 큰 값이 UB를 유발 한다는 것을 증명할 수 있었으며 UB가 없다고 가정 할 수 있기 때문에 173보다 크지 않다고 가정 할 수도 i있습니다. 그런 다음 이것이 i < 300항상 참 임을 추가로 증명할 수 있습니다. 루프 조건을 최적화 할 수 있습니다.

왜 4169이고 다른 가치가 아닌가?

이러한 사이트는 표시되는 출력 줄 (또는 문자 또는 바이트) 수를 제한하고 동일한 제한을 공유합니다.


"정의되지 않은 동작은 정의되지 않았습니다." (씨)

codechef에서 사용되는 컴파일러는 다음 논리를 사용하는 것 같습니다.

  1. 정의되지 않은 동작은 발생할 수 없습니다.
  2. i * 12345678오버플로되고 UB if i > 173(32 비트라고 가정 int)가됩니다.
  3. 따라서, i초과 할 수 없다 173.
  4. 따라서 i < 300불필요하며 true.

루프 자체는 무한한 것처럼 보입니다. 분명히 codechef는 특정 시간이 지나면 프로그램을 중지하거나 출력을 자릅니다.


최대 값이 아직 정의되지 않은 동작으로 평가 되기 때문에 루프 내부의 174 번째 반복에서 정의되지 않은 동작을 호출 하고 있습니다. 따라서 특히 귀하의 경우에 최적화 플래그가 설정된 GCC 컴파일러에서 UB의 효과를 관찰하고 있습니다. 컴파일러가 다음 경고를 발행하여 이에 대해 경고했을 가능성이 있습니다.forint2147483647174 * 1234567892148147972

warning: iteration 174 invokes undefined behavior [-Waggressive-loop-optimizations]

-O2다른 결과를 관찰 하려면 ( ) 최적화 플래그를 제거하십시오 .


컴파일러는 정의되지 않은 문제가 발생하지 않을 것이라고 가정 할 수 있으며, 서명 오버 플로우가 UB 때문에, 결코 있다고 가정 할 수 있습니다 i * 12345678 > INT_MAX, 따라서도 i <= INT_MAX / 12345678 < 300따라서 체크를 해제합니다 i < 300.

참고 URL : https://stackoverflow.com/questions/48731306/program-behaving-strangely-on-online-ides

반응형