“IB”와“UB”는 정확히 무엇을 의미합니까?


110

저는 "IB"와 "UB"라는 용어가 특히 C ++의 맥락에서 여러 번 사용되는 것을 보았습니다. 인터넷 검색을 시도했지만 두 글자로 된 조합이 많이 사용됩니다. :피

그래서 묻습니다 ... 그들이 나쁜 것 같다고해서 무슨 뜻입니까?


5
다른 사람의 수정 사항을 롤백하기로 결정한 경우 철자, 구두점 및 문법이 완벽한 지 확인하십시오. 원본 텍스트에 비해 상당히 개선 된 편집 내용을 롤백하는 것은 의미가 없습니다.
Robert Harvey

답변:


139

IB : 구현 정의 동작. 표준은 정확한 동작을 정의하기 위해 특정 컴파일러 / 플랫폼에 맡기지 만 정의해야합니다.

구현 정의 동작을 사용하면 유용 할 수 있지만 코드의 이식성이 떨어집니다.

UB : 정의되지 않은 행동. 표준은 정의되지 않은 동작을 호출하는 프로그램의 동작 방식을 지정하지 않습니다. 이론적으로 악마가 코에서 날아 오르게 할 수 있기 때문에 "코 악마"라고도합니다.

정의되지 않은 동작을 사용하는 것은 거의 항상 나쁜 생각입니다. 때때로 작동하는 것처럼 보이지만 환경, ​​컴파일러 또는 플랫폼의 변경으로 인해 코드가 임의로 손상 될 수 있습니다.


11
나는 C ++에서 정의되지 않은 동작을 사용하기 때문에 누군가의 코에서 날아 오는 악마를 기다리고있다. 나는 첫 번째 컴파일러가 새로운 C ++ 표준을 완전히 준수 할 때 일어날 것이라고 생각합니다.
OregonGhost

4
@OregonGhost : 당신이 옳은 것 같아요. 나는 유니콘과 함께 일어나는 것을 몇 번 보았지만 악마는 결코 아닙니다.
Thomas

33
@OregonGhost-표준은 악마가 가져야하는 뿔 수를 지정하지 않습니다.
DVK

5
@Michael Burr : 저는 "catch fire"를 선호합니다. 그것은 분명히 재앙 적이며 적어도 그럴듯한 분위기를 가지고 있습니다 (컴퓨터 하드웨어는 때때로이 스레드를 읽고있는 시스템의 경우 소프트웨어 오류가 아닌 하드웨어 이유로 인해 불이 붙습니다).
Steve Jessop

1
이 질문에 답한 사람이 30k보다 낮은 평판을 얻지 못했던 것은 재밌습니다.

19

구현 정의 동작 및 정의되지 않은 동작

C ++ 표준은 다양한 구조의 효과에 대해 매우 구체적이며 특히 다음과 같은 문제 범주를 항상 인식해야합니다 .

  • 정의되지 않은 동작은 보장이 전혀 없음을 의미합니다. 코드가 작동하거나 하드 드라이브에 불이 붙거나 악마가 코 밖으로 날아갈 수 있습니다 . C ++ 언어에 관한 한, 절대적으로 어떤 일이 일어날 수 있습니다. 실제로 이것은 일반적으로 복구 할 수없는 버그가 있음을 의미합니다. 이런 일이 발생하면 애플리케이션에 대해 어떤 것도 신뢰할 수 없습니다 (이 정의되지 않은 동작의 영향 중 하나가 나머지 앱에서 사용하는 메모리를 엉망으로 만들었을 수 있기 때문입니다). 일관성이 필요하지 않으므로 프로그램을 두 번 실행하면 다른 결과를 얻을 수 있습니다. 달의 위상, 입고있는 셔츠의 색상 또는 절대적으로 다른 것에 따라 달라질 수 있습니다.

  • 지정되지 않은 동작은 프로그램이 정상적이고 일관된 작업을 수행해야 함을 의미하지만 이 를 문서화 할 필요는 없습니다 .

  • 구현 정의 동작은 지정되지 않은 것과 유사하지만 컴파일러 작성자가 문서화해야합니다. 이것의 예는 reinterpret_cast. 일반적으로 주소를 수정하지 않고 단순히 포인터 유형을 변경하지만 매핑은 실제로 구현에 정의되어 있으므로 컴파일러 가이 선택을 문서화하는 한 완전히 다른 주소로 매핑 할 있습니다. 또 다른 예는 int의 크기입니다. C ++ 표준은 2 바이트, 4 바이트 또는 8 바이트인지 상관하지 않지만 컴파일러에서 문서화 해야합니다 .

그러나이 모든 것의 공통점은 피하는 것이 가장 좋다는 것입니다. 가능하면 C ++ 표준 자체에 지정된 100 % 동작을 고수하십시오. 그렇게하면 이식성이 보장됩니다.

구현에 정의 된 일부 동작에도 의존해야하는 경우가 많습니다. 피할 수 없을 수도 있지만 여전히주의를 기울여야하며 다른 컴파일러간에 변경 될 수있는 무언가에 의존하고 있음을 인식해야합니다.

반면에 정의되지 않은 동작은 항상 피해야합니다. 일반적으로 프로그램이 어떤 식 으로든 폭발적으로 만든다고 가정해야합니다.


1
이식성에 관심이 있다면 UB를 피해야 합니다 . 특정 구현은 정의되지 않은 특정 동작에 대해 어떤 일이 발생하는지 정의 할 수 있으며 일부 경우 (특히 장치 드라이버 및 소형 임베디드 시스템) 이러한 것들을 사용해야합니다.
Jerry Coffin

3
@Jerry : 아니요, UB 가 완전히 정의되지 않은 경우 피해야 합니다 . 플랫폼 / 구현 / 런타임 / 컴파일러가 추가 보장을 제공하면 동작에 의존하고 이식성을 잃을 수 있습니다. 그러나 그것은 더 이상 정의되지 않은 것이 아닙니다.하지만 대부분의 경우 그러한 보장이 없으며 정의되지 않은 것은 정의되지 않은 것이며 어떤 대가를 치르더라도 피해야합니다.
jalf

"일관성"은 지정되지 않은 동작에 대한 잘못된 설명 일 수 있습니다. 이 표현은 "지정되지 않은 값"그 결과가 있어야합니다 경우, 예를 들어, 작업의 일반적인 문맥과 일치하는 는 그래서 그 다음 저장된 값은 이후 자체와 동일한 비교해야합니다 저장 한 경우, 값을. 그러나 지정되지 않은 결과는 시간이 지남에 따라 일관성이 있거나 (다시 실행하는 경우 동일한 입력에 대해 동일한 출력), 심지어 결정적 일 필요도 없습니다.
Steve Jessop

"더 이상 정의되지 않음"- 표준에 의해 정의되지 않은 것과 정확히 일치 하며 UB는 표준에 의해 정의되지 않은 약식 의미입니다. 귀하의 예에서는 구현에 의해 정의됩니다. 객체 코드를 확인하고 다시 컴파일 할 계획이 없다면 표준 또는 구현에 정의되지 않은 동작에 의존 할 수 있습니다. ;-)
Steve Jessop

"그 후에는 자신과 동일하게 비교해야합니다". 음, NaN이 아니면. 어쨌든 해당 유형에 필요한 모든 동작이 있어야합니다.
Steve Jessop

8
  • IB : 구현 정의 동작입니다. 컴파일러는 수행하는 작업을 문서화해야합니다. >>음수 값에 대한 연산을 수행하는 것이 예입니다.

  • UB : 정의되지 않은 동작-컴파일러는 단순히 충돌하거나 예측할 수없는 결과를 제공하는 등 모든 작업을 수행 할 수 있습니다. 널 포인터를 역 참조하는 것은이 범주에 속하지만 배열 객체의 경계를 벗어나는 포인터 산술과 같은 미묘한 것도 포함합니다.

또 다른 관련 용어는 '지정되지 않은 행동'입니다. 이것은 구현 정의 및 정의되지 않은 동작 사이의 종류입니다. 지정되지 않은 동작의 경우 컴파일러는 표준에 따라 작업을 수행해야하지만 표준이 제공하는 선택 사항은 컴파일러에 따라 다르며 정의 할 필요가 없습니다 (또는 일관성이 있음). 하위 표현식의 평가 순서와 같은 것이이 범주에 속합니다. 컴파일러는 원하는 순서대로 이러한 작업을 수행 할 수 있으며 다른 빌드 또는 동일한 빌드의 다른 실행에서도 다르게 수행 할 수 있습니다 (가능성은 낮지 만 허용됨).


4

짧은 버전 :

구현 정의 동작 (IB) : 올바르게 프로그래밍되었지만 확정되지 않음 *

정의되지 않은 동작 (UB) : 잘못 프로그래밍 됨 (예 : 버그 !)

*) 언어 표준에 관한 한 "미확정"은 물론 고정 플랫폼에서 결정됩니다.


표준이 작업이 구현 정의 동작을 호출한다고 표시하는 경우 해당 작업에서 발생 하는 일관된 동작 을 지정하기 위해 구현이 필요합니다 . 불행히도 가능한 결과를 지정하기 위해 구현이 필요한 행동 범주는 없지만 특정 결과가 지속적으로 발생하도록 요구되지는 않습니다.
supercat

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.