c++ - 정의되지 않고 구체화되지 않은 구현 정의 동작




c++ undefined behavior (6)

C 및 C ++의 정의되지 않은, 지정되지 않은, 구현 정의 동작의 차이점은 무엇입니까?


C ++ 표준 n3337 § 1.3.10 구현 정의 동작

행동, 올바른 형식의 프로그램 구조 및 올바른 데이터, 구현에 의존하며 각 구현 문서

때때로 C ++ 표준은 일부 구문에 특정 동작을 부과하지 않지만 특정 구현 (라이브러리 버전)에 따라 명확하고 명확하게 정의 된 동작을 선택하고 설명 해야한다고 말합니다. 따라서 사용자는 Standard가 이것을 설명하지 않더라도 프로그램이 어떻게 동작하는지 정확히 알 수 있습니다.

C ++ 표준 n3337 § 1.3.24 정의되지 않은 동작

[Note :이 국제 표준이 행동의 명시 적 정의를 생략하거나 프로그램이 잘못된 구성이나 오류가있는 데이터를 사용하는 경우 정의되지 않은 행동이 예상 될 수있다. 허용되지 않은 정의되지 않은 동작은 예측할 수없는 결과로 상황을 완전히 무시하고 환경의 문서화 된 방식 (진단 메시지 발행 여부와 상관없이)에서 번역 또는 프로그램 실행 중에 동작하거나 번역 또는 실행 종료 (발급 진단 메시지의). 많은 잘못된 프로그램 구성은 정의되지 않은 동작을 유발하지 않습니다. 그들은 진단 받아야합니다. - 끝말]

프로그램이 C ++ 표준에 따라 정의되지 않은 구문을 만나면 원하는 작업 (어쩌면 전자 메일을 보내거나 전자 메일을 보내거나 코드를 완전히 무시할 수 있음)을 수행 할 수 있습니다.

C ++ 표준 n3337 § 1.3.25 지정되지 않은 동작

행동 양식, 구현에 따라 올바른 형식의 프로그램 구조와 올바른 데이터를 얻을 수 있습니다. [참고 : 구현시 어떤 동작이 발생하는지 기록 할 필요가 없습니다. 가능한 행동의 범위는 일반적으로이 국제 표준에 의해 규정된다. - 끝말]

C ++ 표준은 일부 구문에 특정 동작을 부과하지 않지만 특정 구현 (라이브러리 버전)에 따라 명확하고 명확하게 정의 된 동작을 선택 해야한다고 설명 합니다. 따라서 설명이 제공되지 않은 경우 사용자가 프로그램이 어떻게 작동하는지 정확하게 알기가 어려울 수 있습니다.


공식 C 이론적 근거 문서

불특정 행동, 정의되지 않은 행동 및 구현이 정의한 행동이라는 용어는 Standard가 제시하지 못하거나 완전히 설명 할 수없는 프로그램을 작성한 결과를 분류하는 데 사용됩니다. 이 분류를 채택하는 목표는 표준에 대한 적합성 표식을 제거하지 않고 구현 품질을 시장에서 적극적인 힘이 될뿐만 아니라 특정 보급형 확장을 허용하는 구현간에 일정한 다양성을 허용하는 것입니다. 표준에 대한 부록 F는이 세 범주 중 하나에 해당하는 행동을 분류합니다.

지정되지 않은 동작 은 구현 자에게 프로그램 변환의 위도를 제공합니다. 이 위도는 프로그램을 번역하지 못하는 범위까지 확장되지 않습니다.

정의되지 않은 동작 은 구현 자 라이센스가 진단하기 어려운 특정 프로그램 오류를 포착하지 못하도록합니다. 또한 가능한 준수 언어 확장 영역을 식별합니다. 구현자는 공식적으로 정의되지 않은 동작의 정의를 제공하여 언어를 보강 할 수 있습니다.

구현에 의해 정의 된 동작은 구현 자 에게 적절한 접근 방식을 자유롭게 선택할 수있게하지만이 선택을 사용자에게 설명해야합니다. 구현 정의로 지정된 비헤이비어는 일반적으로 사용자가 구현 정의를 기반으로 의미있는 코딩 결정을 내릴 수있는 비헤이비어입니다. 이행자 정의의 범위를 결정할 때 구현자는이 기준을 염두에 두어야한다. 명시되지 않은 동작과 마찬가지로 구현 정의 동작을 포함하는 소스를 단순히 번역하지 못하는 것이 적절한 응답이 아닙니다.


글쎄, 이것은 기본적으로 표준의 복사 - 붙여 넣기입니다.

3.4.1 1 구현 정의 동작 (implementation-defined behavior) 각각의 구현이 선택이 어떻게 이루어 졌는지 문서화하는 불특정 행동

2 예제 구현 정의 동작의 예는 부호있는 정수가 오른쪽으로 시프트 될 때 상위 비트를 전파하는 것입니다.

3.4.3 정의되지 않은 또는 잘못된 프로그램 구조 또는 오류가있는 데이터를 사용할 때 정의되지 않은 행동 행위.이 국제 표준은 요구 사항을 부과하지 않는다.

2 유의할 수있는 정의되지 않은 동작은 예측할 수없는 결과로 상황을 완전히 무시한 것, 환경의 문서화 된 방식으로 변환 또는 프로그램 실행 중에 (진단 메시지 발급 여부와 상관없이), 변환 또는 실행을 종료하는 것 진단 메시지의 발행).

3 예 정의되지 않은 동작의 예는 정수 오버플로에 대한 동작입니다.

3.4.4 지정되지 않은 행동의 불특정 행동 (unspecified behavior ) 또는이 국제 표준이 둘 이상의 가능성을 제공하고 어떤 경우에 선택되는지에 대한 추가 요구 사항을 부과하지 않는 기타 행동

2 예 지정되지 않은 동작의 예는 함수에 대한 인수가 평가되는 순서입니다.


어떤 경우에는 유용하고 예측 가능한 방식으로 동작해야하는 많은 구조가 있지만 모든 구현에서 모든 경우에 실제로 그렇게 할 수는 없습니다. 종종 구문을 사용할 수있는 일련의 사례는 대상 플랫폼 및 응용 프로그램 필드에 따라 달라집니다. 다른 목표 및 필드에 대한 구현은 다른 사례 집합을 처리해야하기 때문에 표준은 구현 사례의 품질 문제로 어떤 사례를 처리해야하는지에 대한 질문을 봅니다. 또한 표준 작성자는 "준수하는"구현이 쓸모없는 품질을 유지하는 것을 금지 할 필요가 없음을 알기 때문에 모든 비 쓰레기 구현이 지원할 것으로 예상하는 사례의 동작을 명시 적으로 명령하지 않아도되는 경우가 종종 있습니다 심지어 위임도없이.

예를 들어, 코드는 다음과 같습니다.

struct foo {int x;} = {0};
int main(void)
{
  foo.x = 1;
  return foo.x-1;
}

N1570 6.5p7에 유형의 lvalue를 제외하고는 struct foo 유형의 객체에 액세스 할 수있는 항목이없는 경우에도 int [ie foo.x ]의 lvalue를 사용하여 struct foo 유형의 객체에 저장된 값에 액세스합니다. struct foo 또는 문자 유형의 lvalue를 포함하지 않으며, 표준에 struct-member-access 표현식을 6.5p7의 요구 사항에서 면제하는 언어가 포함되어 있지 않습니다.

분명히 간단한 struct-member-access 표현식을 처리 할 수없는 컴파일러는 예외적으로 낮은 품질이며 아마도 많은 부분에 적합하지 않은 것으로 간주되어야합니다. 결과적으로, 표준 구현 여부에 상관없이 품질 구현물을 생산하고자하는 사람은 그러한 구성을 지원할 것으로 기대하는 것이 타당합니다. 컴파일러 작성자가 자신의 의도 된 목적에 적합한 품질의 컴파일러를 생산하기 위해 선의의 노력을 기울이고 컴파일러가 적합하지 않거나 적합하지 않은 목적에 대해 공개적으로 노력한다면 표준 폐 잉크를 가질 이유가 없습니다 명백해야 할 일들을 진술하려합니다. 사용 가능하고 예측 가능한 동작을 가져야하는 많은 동작은 실제로 정의되지 않은 동작입니다. 표준 작성자는 동작이 정의되지 않은 동작을 창 밖의 판단을 내리기위한 변명으로 호출한다는 사실을 사용하는 대신 합리적인 판단을 수행하도록 신뢰할 수 있기 때문입니다. .


역사적으로 Implementation-Defined Behavior와 Undefined Behavior는 표준의 저자가 품질 구현을 작성하는 사람들이 어떤 동작 보증이 있을지 결정하기 위해 판단을 사용할 것이라고 예상 한 상황을 나타 냈습니다. 의도 한 목표. 하이 엔드급 코드의 필요성은 저수준 시스템 코드의 요구 사항과 상당히 다르며 UB와 IDB는 컴파일러 작성자에게 다양한 요구 사항을 충족시킬 수있는 유연성을 제공합니다. 어느 카테고리도 구현이 특정 목적이나 심지어 어떤 목적 으로든 유용한 방식으로 작동하도록 요구하지는 않습니다. 그러나 특정 목적에 적합하다고 주장하는 품질 구현 은 표준이 요구하든 그렇지 않든 그러한 목적에 부합하는 방식으로 행동해야합니다.

구현 정의 동작과 정의되지 않은 동작의 유일한 차이점은 구현을 통해 수행 할 수있는 일이 아무리 유용 할지라도 구현에서 일관된 동작을 정의하고 문서화해야한다는 입니다. 그들 사이의 구분선은 구현이 행동을 정의하는 데 일반적으로 유용한 지 여부 (컴파일러 작성자는 표준에서 필요로하는지 여부에 관계없이 실용적으로 유용한 동작을 정의해야 함)가 아니라 동작을 정의하는 것이 동시에 비용이 많이 드는 구현이 가능한지 여부 쓸데없는 . 그러한 구현이 존재할 수도 있다는 판단은 어떤 식 으로든 형성되거나 형성되지 않으며 다른 플랫폼에서 정의 된 동작을 지원하는 유용성에 대한 판단을 내포합니다.

불행하게도, 1990 년대 중반의 컴파일러 제작자들은 행동 위임의 부족을 행동 필수 항목이 필수적인 응용 분야, 심지어 실제 비용이 들지 않는 시스템에서도 비용 가치가 없다는 판단으로 해석하기 시작했습니다. 합리적인 판단을하기위한 초청으로 UB를 대우하는 대신, 컴파일러 작가들은 그것을 그렇게하지 않을 핑계로 취급하기 시작했습니다.

예를 들어 다음 코드가 주어집니다.

int scaled_velocity(int v, unsigned char pow)
{
  if (v > 250)
    v = 250;
  if (v < -250)
    v = -250;
  return v << pow;
}

2의 보수를 구현하면 v 가 양수인지 음수인지에 관계없이 표현식을 2의 보수로 간주 할 수 있습니다.

그러나 오늘날의 컴파일러 작성자들 사이에서 선호하는 철학은 프로그램이 정의되지 않은 행동에 참여할 경우에만 v 가 음수가 될 수 있기 때문에 프로그램에 v 의 음수 범위를 집어 넣을 이유가 없음을 제안합니다. 유의미한 모든 단일 컴파일러에서 지원되는 데 사용 된 음수 값의 왼쪽 이동과 기존 코드의 상당 부분이 해당 동작에 의존한다고해도 표준에서 좌변 이동하는 음수 값은 다음과 같이 UB로 표시된다는 사실을 현대 철학은 해석합니다. 컴파일러 작성자가이를 무시해도된다는 것을 의미합니다.


정의되지 않은 행동 대 명시되지 않은 행동 에는 짧은 설명이 있습니다.

그들의 최종 요약 :

정리하자면, 불특정 행동은 대개 소프트웨어를 휴대 할 필요가 없다면 걱정할 필요가없는 것입니다. 반대로 정의되지 않은 동작은 항상 바람직하지 않으므로 발생하지 않아야합니다.







unspecified-behavior