문제

내 독서에서 이해할 수 있듯이 정의되지 않은 행동은 컴파일 시간에 몇 가지 비 동일한 대안으로 컴파일러를 떠난 결과입니다. 그러나 그렇지 않으면 엄격한 코딩 관행 (각 과제와 각 평등을 별도의 명세서에 넣고 적절한 디버깅 및 댓글을 작성하는 것과 같이)이라는 것을 의미하지는 않습니다. -행동.

또한, 각 오류마다, 코드를 식별하면 해당 특정 명령문의 Stead에서 어떤 진술을 사용할 수 있는지 알아야합니까?

편집 : 글을 쓰지 않은 코드를 작성한 장소에는 관심이 없습니다. 수학적 논리에 의해 소리가 나오는 코드가 작동하지 않는 예제에 관심이 있습니다.

또한, 나는 '좋은 코딩 실습'이 몇 줄마다 강력한 유익한 의견, 적절한 들여 쓰기 및 덤프를 정기적으로 디버깅하는 것으로 간주합니다.

도움이 되었습니까?

해결책

정의되지 않은 동작이 반드시 여러 대안으로 컴파일러를 떠나는 것은 아닙니다. 가장 일반적으로 그것은 단순히 말이되지 않는 일을하는 것입니다.

예를 들어,이 코드를 선택하십시오.

int arr[2];
arr[200] = 42;

이것은 정의되지 않은 행동입니다. 컴파일러에 선택할 수있는 여러 가지 대안이 주어진 것은 아닙니다. 내가하는 일은 말이되지 않는 것입니다. 이상적으로는 처음에는 허용되지 않아야하지만 잠재적으로 비싼 런타임 확인 없이는 코드에서 이와 같은 것이 발생하지 않을 것이라고 보장 할 수 없습니다. 따라서 C ++에서 규칙은 단순히 언어가 규칙을 고수하는 프로그램의 동작 만 지정한다는 것입니다. 위의 예에서처럼 잘못된 일을한다면 단순히 한정되지 않은 무슨 일이 있어야합니다.

이제이 오류를 어떻게 감지 할 것인지 상상해보십시오. 어떻게 표면할까요? 그것은 수도 절대 어떤 문제도 일으키는 것 같습니다. 아마도 우리는 프로세스에 매핑 된 메모리에 글을 쓰는 것입니다 (따라서 액세스 위반을받지 못합니다). 그러나 다른 방법으로 사용되지 않습니다 (따라서 프로그램의 다른 부분은 우리의 쓰레기 가치를 읽거나 우리가 쓴 것을 덮어 쓰지 않을 것입니다. ). 그러면 프로그램에 버그가없는 것처럼 보이며 잘 작동합니다.

또는 우리의 프로세스에도 매핑되지 않은 주소에 도달 할 수도 있습니다. 그러면 프로그램이 즉시 충돌합니다.

또는 우리의 프로세스에 매핑 된 주소에 도달 할 수도 있지만 어느 시점에서 나중에 무언가에 사용될 것입니다. 그러면 우리가 아는 것은 조만간 그 주소에서 읽는 기능이 예상치 못한 값을 얻을 것이며 이상하게 행동한다는 것입니다. 그 부분은 디버거에서 쉽게 발견 할 수 있지만, 우리에게 아무 말도하지 않습니다. 언제 또는 어디 그 쓰레기 가치가 작성되었습니다. 따라서 오류를 소스로 추적하는 간단한 방법은 없습니다.

다른 팁

먼저 C ++ 03 표준의 일부 정의 :

1.3.5 구현 정의 행동

구현에 따라 다르고 각 구현이 문서화 해야하는 잘 형성된 프로그램 구성 및 올바른 데이터에 대한 행동

1.3.12 정의되지 않은 행동

이 국제 표준이 요구 사항을 부과하는 잘못된 프로그램 구성 또는 잘못된 데이터를 사용하여 발생할 수있는 행동과 같은 행동. 이 국제 표준이 명시 적 정의 나 행동에 대한 설명을 생략 할 때 정의되지 않은 행동도 예상 될 수 있습니다.

1.3.13 지정되지 않은 행동

잘 형성된 프로그램 구성 및 올바른 데이터에 대한 행동은 구현에 따라 다릅니다. 어떤 동작이 발생하는지 문서화하기 위해 구현이 필요하지 않습니다.

일지라도 지정되지 않은 행동 UB라고 할 수 있습니다. 나는 그것을 본 적이 없으며 UB는 항상 의미합니다. 정의되지 않은 행동. 표준 전체에는 "X를 수행하지 않은 동작"과 유사한 진술이 있지만 때로는 단순히 다루지 않는 경우가 발생합니다.

정의를 다른 방식으로 배치하려면 어디서나 정의되지 않은 동작이 있으면 모든 베팅이 꺼져 있습니다. 표준에 관한 한, 귀하의 프로그램은 Superbowl Weekend를 위해 시어머니를 초대하여 무엇이든 할 수 있습니다. Nethack 달리기. UB의 본질로 인해 테스트 할 수 없으며 컴파일러의 도움을 기대할 수 없습니다. (일부 사소한 경우, 일반적인 오류 컴파일러는 일반적으로 진단을 생성합니다.)

일반적으로 무언가는 논리적으로 의미가 없기 때문에 UB로 정의됩니다 (예 : 한계에서 배열에 액세스하는 것은 종종 구현이 너무 많은 작업을 수행하기 위해서는 런타임에 종종 - 종종 런타임을 예방해야하기 때문에 종종 UB로 정의됩니다. C ++는 C에서 파생되었으며 고도로 최적화 된 프로그램을 생산할 수 있다는 것은 두 언어의 주요 목표입니다. 이를 위해 언어는 프로그래머에게 연기하여 이러한 상황에서 코드가 올바른지 확인하여 "사용하지 않는 금액을 지불하지 않습니다"원칙과 관련하여 코드가 올바른지 확인합니다.

마침내 UB는 나쁘고 매우 나쁩니다. 모든 비용으로 피하십시오. 그러나 UB의 어려운 부분은 그것이 무엇인지 또는 어떤 상황에서 발생하는지 알지 못합니다. 어려운 부분은 UB를 호출 할 때 인식하는 것입니다. 예를 들어:

std::string s = "abc";
char& c = s[0];
cout.write(s.data(), s.length());
c = '-';

완벽하게 합리적으로 보입니다. 아니, 이것은 아직 UB입니다 모든 인기있는 구현에서 기대하는대로 작동합니다.

"정의되지 않은 동작"에 대한 공식적인 정의가 있는지 확실하지 않지만 좋은 코딩 표준을 따르면 모호성을 줄이고 컴파일 및 런타임 결함을 줄일 수 있습니다.

그러나 두 프로그래머가 "좋은 코딩 표준"에 동의하도록하는 것은 복잡하고 오류가 발생하기 쉬운 프로세스입니다.

두 번째 질문에는 예 컴파일러가 일반적으로 문제를 해결하는 데 사용할 수있는 오류 코드를 출력합니다.

내 독서에서 이해할 수 있듯이 정의되지 않은 행동은 컴파일 시간에 몇 가지 비 동일한 대안으로 컴파일러를 떠난 결과입니다.

그럴 수도 있습니다 하나 정의되지 않은 행동의 근원, 당신은 너무 추상적으로 말하고 있습니다. "컴파일 시간에 비 동일 대안"이 의미하는 바에 대한 구체적인 예가 필요합니다.

"엄격한 코딩 실습을 따르십시오"라면 정의되지 않은 동작을 초래하는 논리를 사용하지 않는다는 것을 의미합니다. 그렇다면 (정의되지 않은 동작이 없기 때문에) 정의되지 않은 동작으로 인해 버그를 추적하는 것은 로직 오류로 인한 버그를 추적하는 것보다 쉽지 않을 수 있습니다.

"정의되지 않은 동작"을 초래하는 코드는 여전히 합법적 인 C ++ 코드입니다. 나는 "정의되지 않은 동작"이 주어진 구현이있는 주어진 플랫폼의 주어진 프로그램에 대해 예측할 수있을 때 거의 사용하지 않는 코드/논리 클래스라고 생각합니다. 언어가 "정의되지 않은 행동"을 고려하는 것이 실제로 특정 환경/제약 세트에 대해 정의 될 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top