답변:
IB : 구현 정의 동작. 표준은 정확한 동작을 정의하기 위해 특정 컴파일러 / 플랫폼에 맡기지 만 정의해야합니다.
구현 정의 동작을 사용하면 유용 할 수 있지만 코드의 이식성이 떨어집니다.
UB : 정의되지 않은 행동. 표준은 정의되지 않은 동작을 호출하는 프로그램의 동작 방식을 지정하지 않습니다. 이론적으로 악마가 코에서 날아 오르게 할 수 있기 때문에 "코 악마"라고도합니다.
정의되지 않은 동작을 사용하는 것은 거의 항상 나쁜 생각입니다. 때때로 작동하는 것처럼 보이지만 환경, 컴파일러 또는 플랫폼의 변경으로 인해 코드가 임의로 손상 될 수 있습니다.
구현 정의 동작 및 정의되지 않은 동작
C ++ 표준은 다양한 구조의 효과에 대해 매우 구체적이며 특히 다음과 같은 문제 범주를 항상 인식해야합니다 .
정의되지 않은 동작은 보장이 전혀 없음을 의미합니다. 코드가 작동하거나 하드 드라이브에 불이 붙거나 악마가 코 밖으로 날아갈 수 있습니다 . C ++ 언어에 관한 한, 절대적으로 어떤 일이 일어날 수 있습니다. 실제로 이것은 일반적으로 복구 할 수없는 버그가 있음을 의미합니다. 이런 일이 발생하면 애플리케이션에 대해 어떤 것도 신뢰할 수 없습니다 (이 정의되지 않은 동작의 영향 중 하나가 나머지 앱에서 사용하는 메모리를 엉망으로 만들었을 수 있기 때문입니다). 일관성이 필요하지 않으므로 프로그램을 두 번 실행하면 다른 결과를 얻을 수 있습니다. 달의 위상, 입고있는 셔츠의 색상 또는 절대적으로 다른 것에 따라 달라질 수 있습니다.
지정되지 않은 동작은 프로그램이 정상적이고 일관된 작업을 수행해야 함을 의미하지만 이 를 문서화 할 필요는 없습니다 .
구현 정의 동작은 지정되지 않은 것과 유사하지만 컴파일러 작성자가 문서화해야합니다. 이것의 예는 reinterpret_cast
. 일반적으로 주소를 수정하지 않고 단순히 포인터 유형을 변경하지만 매핑은 실제로 구현에 정의되어 있으므로 컴파일러 가이 선택을 문서화하는 한 완전히 다른 주소로 매핑 할 수 있습니다. 또 다른 예는 int의 크기입니다. C ++ 표준은 2 바이트, 4 바이트 또는 8 바이트인지 상관하지 않지만 컴파일러에서 문서화 해야합니다 .
그러나이 모든 것의 공통점은 피하는 것이 가장 좋다는 것입니다. 가능하면 C ++ 표준 자체에 지정된 100 % 동작을 고수하십시오. 그렇게하면 이식성이 보장됩니다.
구현에 정의 된 일부 동작에도 의존해야하는 경우가 많습니다. 피할 수 없을 수도 있지만 여전히주의를 기울여야하며 다른 컴파일러간에 변경 될 수있는 무언가에 의존하고 있음을 인식해야합니다.
반면에 정의되지 않은 동작은 항상 피해야합니다. 일반적으로 프로그램이 어떤 식 으로든 폭발적으로 만든다고 가정해야합니다.
IB : 구현 정의 동작입니다. 컴파일러는 수행하는 작업을 문서화해야합니다. >>
음수 값에 대한 연산을 수행하는 것이 예입니다.
UB : 정의되지 않은 동작-컴파일러는 단순히 충돌하거나 예측할 수없는 결과를 제공하는 등 모든 작업을 수행 할 수 있습니다. 널 포인터를 역 참조하는 것은이 범주에 속하지만 배열 객체의 경계를 벗어나는 포인터 산술과 같은 미묘한 것도 포함합니다.
또 다른 관련 용어는 '지정되지 않은 행동'입니다. 이것은 구현 정의 및 정의되지 않은 동작 사이의 종류입니다. 지정되지 않은 동작의 경우 컴파일러는 표준에 따라 작업을 수행해야하지만 표준이 제공하는 선택 사항은 컴파일러에 따라 다르며 정의 할 필요가 없습니다 (또는 일관성이 있음). 하위 표현식의 평가 순서와 같은 것이이 범주에 속합니다. 컴파일러는 원하는 순서대로 이러한 작업을 수행 할 수 있으며 다른 빌드 또는 동일한 빌드의 다른 실행에서도 다르게 수행 할 수 있습니다 (가능성은 낮지 만 허용됨).
짧은 버전 :
구현 정의 동작 (IB) : 올바르게 프로그래밍되었지만 확정되지 않음 *
정의되지 않은 동작 (UB) : 잘못 프로그래밍 됨 (예 : 버그 !)
*) 언어 표준에 관한 한 "미확정"은 물론 고정 플랫폼에서 결정됩니다.
UB : 정의되지 않은 동작
IB : 구현 정의 동작