C 코드에서 배열의 끝 부분에 액세스하는 코드를 의도적으로 생성하는 DSP 칩 용 컴파일러로 작업하고 있습니다.
반복의 끝이 다음 반복을 위해 일부 데이터를 프리 페치하도록 루프가 구성되어 있기 때문입니다. 따라서 마지막 반복이 끝날 때 프리 페치 된 데이텀은 실제로 사용되지 않습니다.
이와 같은 C 코드를 작성하면 정의되지 않은 동작이 발생하지만 이는 최대 이식성과 관련된 표준 문서의 형식 일뿐입니다.
더 자주, 그렇지 않은 경우, 범위를 벗어나는 프로그램은 영리하게 최적화되지 않습니다. 그것은 단순히 버그입니다. 이 코드는 가비지 값을 가져오고 앞에서 언급 한 컴파일러의 최적화 된 루프와 달리 이후 계산에서이 값 을 사용 하여 결과를 손상시킵니다.
이와 같은 버그를 잡는 것이 가치가 있으며, 그 이유만으로도 동작을 정의하지 않아도됩니다. 즉, 런타임이 "main.c의 42 행에서 배열 오버런"과 같은 진단 메시지를 생성 할 수 있습니다.
가상 메모리가있는 시스템에서는 다음에 오는 주소가 매핑되지 않은 가상 메모리 영역에 있도록 배열이 할당 될 수 있습니다. 그러면 액세스가 프로그램을 폭격합니다.
따로, C에서는 배열의 끝을 지나는 포인터를 만들 수 있습니다. 그리고이 포인터는 배열의 내부에 대한 포인터보다 크게 비교해야합니다. 이것은 C 구현이 메모리의 끝에 배열을 배치 할 수 없다는 것을 의미합니다. 하나의 더하기 주소가 배열의 다른 주소보다 줄어든 것처럼 보입니다.
그럼에도 불구하고, 초기화되지 않았거나 범위를 벗어난 값에 액세스하는 것은 최대로 이식 가능하지 않더라도 때때로 유효한 최적화 기술입니다. 이는 예를 들어 Valgrind 도구가 액세스가 발생할 때 초기화되지 않은 데이터에 대한 액세스를보고하지 않고 나중에 프로그램의 결과에 영향을 줄 수있는 방식으로 값이 사용되는 경우에만 발생합니다. "xxx : nnn의 조건부 분기는 초기화되지 않은 값에 따라 다릅니다"와 같은 진단을받으며 원래 위치를 추적하기가 어려운 경우가 있습니다. 이러한 모든 액세스가 즉시 갇히게되면 컴파일러 최적화 코드와 올바르게 수동 최적화 된 코드에서 발생하는 많은 오 탐지가 발생합니다.
말하자면, Linux로 포팅하고 Valgrind에서 실행될 때 이러한 오류를 발생시키는 공급 업체의 일부 코덱으로 작업하고있었습니다. 그러나 공급 업체는 몇 비트 만실제로 사용되는 값 중 하나는 초기화되지 않은 메모리에서 왔으며 해당 비트는 논리에 의해 신중하게 피했습니다. 값의 올바른 비트 만 사용되었으며 Valgrind는 개별 비트를 추적 할 수 없습니다. 초기화되지 않은 자료는 인코딩 된 데이터의 비트 스트림 끝을지나 단어를 읽었을 때 발생했지만 코드는 스트림에 몇 비트가 있는지 알고 실제로 실제보다 많은 비트를 사용하지 않습니다. 비트 스트림 배열의 끝을 넘어서 액세스해도 DSP 아키텍처에 아무런 해를 끼치 지 않기 때문에 (어레이 다음에는 가상 메모리가없고, 메모리 매핑 된 포트가없고, 주소가 랩핑되지 않습니다) 유효한 최적화 기술입니다.
ISO C에 따르면 단순히 C 표준에 정의되지 않은 헤더를 포함하거나 프로그램 자체 또는 C 표준에 정의되지 않은 함수를 호출하는 것은 정의되지 않은 예이므로 "정의되지 않은 동작"은 실제로 의미가 없습니다. 행동. 정의되지 않은 동작은 "지구상의 누군가가 정의하지 않음", "ISO C 표준에 의해 정의되지 않음"을 의미하지 않습니다. 그러나 물론, 때로는 정의되지 않은 동작이 정말 됩니다 절대적으로 누군가에 의해 정의되어 있지 않습니다.