문제

최근 프로젝트를 진행하는 동안 고객 QA 담당자가 저를 방문했는데, 그 사람이 저에게 전에는 전혀 고려하지 않았던 질문을 했습니다.

사용 중인 컴파일러가 C 코드의 기능과 정확하게 일치하는 기계어 코드를 생성하고 컴파일러가 완전히 결정적이라는 것을 어떻게 알 수 있습니까?

나는 항상 컴파일러를 당연하게 여겼기 때문에 이 질문에 대해 전혀 대답할 수 없었습니다.코드를 받아들이고 기계어 코드를 뿜어냅니다.내가 요청하지 않은 기능을 컴파일러가 실제로 추가하지 않는지 어떻게 테스트하고 테스트할 수 있습니까?아니면 내가 기대하는 것과 약간 다른 방식으로 코드를 더욱 위험하게 구현하고 있습니까?

나는 이것이 아마도 모든 사람에게 실제로 문제가 되지 않을 것이라는 것을 알고 있으며 실제로 대답은 다음과 같습니다."당신은 배럴을 넘었고 그것을 처리합니다."그러나 임베디드 환경에서 작업할 때는 컴파일러를 암묵적으로 신뢰합니다.그렇게 하는 것이 옳다는 것을 나 자신과 QA에게 어떻게 증명할 수 있습니까?

도움이 되었습니까?

해결책

안전이 중요한 임베디드 애플리케이션 인증 기관에서는 컴파일러에 대한 "사용 입증" 요구 사항을 충족해야 합니다.일반적으로 세부 문서를 통해 충족되고 입증되어야 하는 특정 요구 사항(예: "작업 시간")이 있습니다.그러나 대부분의 사람들은 이러한 요구 사항을 충족할 수 없거나 충족하기를 원하지 않습니다. 특히 새로운 타겟/컴파일러를 사용하는 첫 번째 프로젝트에서는 매우 어려울 수 있기 때문입니다.

또 다른 접근 방식은 기본적으로 컴파일러의 출력을 전혀 신뢰하지 않는 것입니다.모든 컴파일러 및 언어 종속적 결함(C-90 표준의 부록 G, 누구든지?)의 결함은 이후의 기능 테스트 외에도 엄격한 정적 분석, 단위 및 적용 범위 테스트 세트로 다루어야 합니다.

다음과 같은 표준 미스라-C 컴파일러에 대한 입력을 C 언어의 "안전한" 하위 집합으로 제한하는 데 도움이 될 수 있습니다.또 다른 접근 방식은 컴파일러에 대한 입력을 언어의 하위 집합으로 제한하고 전체 하위 집합에 대한 출력이 무엇인지 테스트하는 것입니다.우리의 애플리케이션이 하위 집합의 구성 요소로만 구축된 경우 컴파일러의 출력이 무엇인지 알 수 있다고 가정합니다.일반적으로 "컴파일러 자격"을 따릅니다.

이 모든 것의 목표는 QA 담당자의 질문에 "우리는 컴파일러의 결정론에만 의존하는 것이 아니라 이것이 우리가 증명하는 방식입니다..."라고 답할 수 있는 것입니다.

다른 팁

해당 인수는 모든 수준에서 적용할 수 있습니다.타사 라이브러리를 신뢰하시나요?OS를 믿나요?당신은 프로세서를 신뢰합니까?

물론 이것이 타당한 우려가 될 수 있는 이유에 대한 좋은 예는 Ken Thompson이 원래 '로그인' 프로그램에 백도어를 삽입한 방법입니다.그리고 C 컴파일러를 수정하여 로그인을 다시 컴파일하더라도 여전히 백도어를 갖게 되었습니다.이것 좀 봐 전기 상세 사항은.

암호화 알고리즘에 대해서도 비슷한 질문이 제기되었습니다. NSA가 스누핑할 수 있는 DES에 백도어가 없다는 것을 어떻게 알 수 있습니까?

결국에는 걱정하지 않을 만큼 구축하고 있는 인프라를 신뢰할 수 있는지 결정해야 합니다. 그렇지 않으면 자체 실리콘 칩 개발을 시작해야 합니다!

테스트를 통해 알 수 있습니다.테스트할 때는 코드와 컴파일러를 모두 테스트하는 것입니다.

여러분이나 컴파일러 작성자가 오류를 범할 확률은 문제의 프로그램을 일부 어셈블리 언어로 작성한 경우 오류를 범할 확률보다 훨씬 작다는 것을 알게 될 것입니다.

사용 가능한 컴파일러 검증 슈트가 있습니다.
내가 기억하는 것은 "다년생".

내가 임베디드 SOC 프로세서용 C 컴파일러 작업을 할 때 우리는 이 컴파일러와 다른 두 가지 검증 슈트(이름은 잊어버렸습니다)에 대해 컴파일러를 검증해야 했습니다.이러한 테스트 슈트에 대한 특정 수준의 적합성에 대해 컴파일러를 검증하는 것이 계약의 일부였습니다.

모든 것은 신뢰로 귀결됩니다.고객이 컴파일러를 신뢰합니까?그것을 사용하거나 최소한 당신과 다른 사람의 출력 코드를 비교하십시오.

신뢰하지 않는 경우 해당 언어에 대한 참조 구현이 있습니까?그들이 그것을 신뢰하도록 설득할 수 있나요?그런 다음 참조와 비교하거나 참조를 사용하십시오.

이 모든 것은 공급업체/공급자로부터 얻은 실제 코드를 실제로 확인하고 컴파일러가 변조되지 않았는지 확인한다고 가정합니다. 이것이 첫 번째 단계입니다.

어쨌든 이것은 참조 없이 컴파일러를 처음부터 어떻게 검증할 것인가에 대한 질문을 여전히 남깁니다.이는 확실히 엄청난 작업처럼 보이며 언어 정의가 필요합니다. 항상 사용할 수 있는 것은 아니며 때로는 정의가 컴파일러인 경우도 있습니다.

사용 중인 컴파일러가 C 코드의 기능과 정확하게 일치하는 기계어 코드를 생성하고 컴파일러가 완전히 결정적이라는 것을 어떻게 알 수 있습니까?

그렇지 않기 때문에 결과 바이너리를 테스트하고 테스트한 것과 동일한 바이너리를 제공해야 합니다.그리고 '사소한' 소프트웨어 변경을 수행할 때 이전 기능이 손상되지 않았는지 확인하기 위해 회귀 테스트를 수행하는 이유는 무엇입니까?

제가 인증한 유일한 소프트웨어는 항공전자공학입니다.FAA 인증은 소프트웨어가 올바르게 작동하는지 입증할 만큼 엄격하지 않으며 동시에 특정 양의 난관을 뛰어넘도록 강요합니다.비결은 '프로세스'를 구조화하여 가능한 한 불필요한 농구대 점프를 최소화하면서 품질을 최대한 향상시키는 것입니다.따라서 당신이 알고 있는 모든 것은 가치가 없으며 실제로 버그를 발견하지 못할 것이므로 아마도 빠져나갈 수 있을 것입니다.그리고 당신이 알고 있는 모든 일을 해야 하기 때문에 ~ 할 것이다 FAA에서 명시적으로 요청하지 않은 버그를 찾으려면 FAA/QA 직원이 요청한 내용을 제공하는 것처럼 들릴 때까지 단어를 비틀는 것이 가장 좋습니다.

이것은 실제로 내가 말한 것만큼 부정직하지는 않습니다. 일반적으로 FAA는 귀하가 성실하고 자신감을 갖는 것에 더 관심을 갖습니다. 견딜 수 없는 당신이 정확히 무엇을 하는지보다, 좋은 일을 하는 것.

국방 소프트웨어 엔지니어를 위한 잡지인 Crosstalk에서 일부 지적 정보를 찾을 수 있습니다.이 질문은 그들이 깨어 있는 데 많은 시간을 보내는 종류의 질문입니다. http://www.stsc.hill.af.mil/crosstalk/2006/08/index.html (이전 프로젝트에서 내 예전 노트를 찾을 수 있다면 여기로 돌아올게요...)

아무리 권장되는 컴파일러라도 완전히 신뢰할 수는 없습니다.버그가 있는 업데이트를 릴리스할 수 있으며 코드는 동일하게 컴파일됩니다.이 문제는 버그가 있는 컴파일러로 오래된 코드를 업데이트하고, 테스트를 수행하고 제품을 배송한 후 3개월 후에 고객이 문제를 알릴 때 더욱 복잡해집니다.

모든 것은 테스트로 돌아오며, 제가 배운 것이 있다면 사소한 변경이 발생한 후에는 철저하게 테스트하라는 것입니다.문제를 찾는 것이 불가능해 보인다면 컴파일된 어셈블러를 살펴보고 그것이 해야 할 일을 하고 있는지 확인하십시오.

여러 번 컴파일러에서 버그를 발견했습니다.한 번은 16비트 변수가 증가하지만 캐리가 없고 16비트 변수가 헤더 파일에 정의된 extern 구조체의 일부인 경우에만 증가하는 버그가 있었습니다.

...당신은 당신의 컴파일러를 암묵적으로 신뢰합니다

컴파일러 버그를 처음 발견하면 이 작업을 중단하게 됩니다.;-)

그러나 궁극적으로 이것이 테스트의 목적입니다.처음에 버그가 제품에 어떻게 유입되었는지는 테스트 체제에 중요하지 않습니다. 중요한 것은 해당 버그가 광범위한 테스트 체제를 통과하지 못했다는 것입니다.

잘..단순히 컴파일러의 출력을 신뢰한다고 말할 수는 없습니다. 특히 임베디드 코드로 작업하는 경우에는 더욱 그렇습니다.동일한 코드를 다른 컴파일러로 컴파일할 때 생성된 코드 사이의 불일치를 찾는 것은 어렵지 않습니다.이는 C 표준 자체가 너무 느슨하기 때문입니다.많은 세부 사항은 표준을 위반하지 않고도 다양한 컴파일러에 의해 다르게 구현될 수 있습니다.우리는 이 물건을 어떻게 처리합니까?우리는 가능할 때마다 컴파일러 종속 구성을 피합니다.우리는 C의 더 안전한 하위 집합을 선택하여 이를 처리할 수 있습니다. 미스라-C 이전에 사용자 cschol이 언급한 대로입니다.컴파일러가 생성한 코드를 검사해야 하는 경우는 거의 없지만 가끔 그런 일이 나에게도 발생했습니다.그러나 궁극적으로는 코드가 의도한 대로 작동하는지 확인하기 위해 테스트에 의존하게 됩니다.

더 나은 옵션이 있습니까?어떤 사람들은 있다고 주장합니다.다른 옵션은 코드를 작성하는 것입니다. 스파크/에이다.저는 SPARK로 코드를 작성한 적이 없지만 "베어메탈" 항목을 처리하는 C로 작성된 루틴에 코드를 연결해야 한다는 것을 알고 있습니다.SPARK/Ada의 장점은 모든 컴파일러에서 생성된 코드가 항상 동일하다는 것을 절대적으로 보장한다는 것입니다.어떠한 모호함도 없습니다.게다가 이 언어를 사용하면 코드의 동작 방식에 대한 설명을 코드에 추가할 수 있습니다.SPARK 도구 세트는 이러한 주석을 사용하여 작성된 코드가 실제로 주석에 설명된 작업을 수행함을 공식적으로 증명합니다.따라서 중요한 시스템의 경우 SPARK/Ada가 매우 좋은 선택이라는 말을 들었습니다.그래도 직접 시도해 본 적은 없습니다.

컴파일러가 기대한 대로 정확하게 작동할지 확신할 수 없습니다.그 이유는 물론이다. 컴파일러는 소프트웨어의 한 조각이다, 따라서 버그에 취약합니다.

컴파일러 작성자는 고품질 사양으로 작업할 수 있는 장점이 있는 반면, 나머지 사람들은 진행하면서 우리가 무엇을 만들고 있는지 파악해야 합니다.그러나 컴파일러 사양 또한 버그가 있고 미묘한 상호작용이 있는 복잡한 부분이 있습니다.따라서 컴파일러가 무엇을 해야 하는지 파악하는 것은 그리 간단한 일이 아닙니다.

그럼에도 불구하고 언어 사양이 무엇을 의미하는지 결정하고 나면 모든 뉘앙스에 대해 훌륭하고 빠르며 자동화된 테스트를 작성할 수 있습니다.이는 컴파일러 작성이 다른 종류의 소프트웨어 작성에 비해 큰 이점을 갖는 부분입니다.테스트 중.모든 버그는 자동화된 테스트 케이스가 되며 테스트 스위트는 매우 철저할 수 있습니다.컴파일러 공급업체는 컴파일러의 정확성을 확인하는 데 투자할 예산이 귀하보다 훨씬 많습니다(이미 본업을 갖고 계시죠?).

이것이 당신에게 무엇을 의미합니까?이는 컴파일러에 버그가 있을 가능성에 대해 열려 있어야 하지만 스스로 버그를 발견하지 못할 가능성이 있다는 것을 의미합니다.

나는 조만간 폐업할 가능성이 없고, 컴파일러의 품질이 우수하며, 제품 서비스(패치) 능력을 입증한 컴파일러 공급업체를 선택하겠습니다.컴파일러는 시간이 지나면서 점점 더 정확해지는 것 같기 때문에 저는 10~20년 정도 된 컴파일러를 선택하겠습니다.

코드를 올바르게 작성하는 데 주의를 집중하세요. 그렇다면 명확하고 단순하다, 그럼 당신이 하다 컴파일러 버그가 발생하면 문제가 어디에 있는지 결정하기 위해 열심히 생각할 필요가 없습니다. 좋은 단위 테스트 작성, 그러면 코드가 예상한 대로 작동하는지 확인할 수 있습니다.

단위 테스트를 시도해 보세요.

충분하지 않다면 다른 컴파일러를 사용하고 단위 테스트 결과를 비교하십시오.strace 출력을 비교하고, VM에서 테스트를 실행하고, 디스크 및 네트워크 I/O 로그를 유지한 다음 이를 비교합니다.

아니면 자신만의 컴파일러를 작성하고 비용이 얼마나 들 것인지 알려주도록 제안하십시오.

가장 쉽게 인증할 수 있는 것은 공급자 X의 변조되지 않은 컴파일러를 사용하고 있다는 것입니다.공급자 X를 신뢰하지 않는다면 그것은 그들의 문제입니다(X가 합리적으로 신뢰할 수 있는 경우).컴파일러 제공자를 신뢰하지 않는다면 완전히 불합리한 것입니다.

그들의 질문에 대답하기:나는 이러한 수단을 통해 X의 변조되지 않은 컴파일러를 사용하고 있는지 확인합니다.X는 평판이 좋으며 애플리케이션이 예상대로 작동하는지 보여주는 멋진 테스트 세트도 있습니다.

다른 모든 것들은 벌레의 캔을 열기 시작했습니다.Rob이 말했듯이 어딘가에서 멈춰야 합니다.

때로는 공격적인 수준의 최적화를 요청할 때 행동 변화가 발생하는 경우도 있습니다.

그리고 최적화와 부동 소수점 숫자는요?잊어 버려!

대부분의 소프트웨어 개발(데스크톱 응용 프로그램을 생각해 보세요)에 대한 대답은 아마도 당신이 모르고 관심도 없다는 것입니다.

안전이 중요한 시스템(원자력 발전소 및 상업용 항공 전자 공학 등)에서는 하다 관리 및 규제 기관에서는 귀하에게 이를 증명하도록 요구할 것입니다.내 경험에 따르면 다음 두 가지 방법 중 하나로 이 작업을 수행할 수 있습니다.

  1. 자격을 갖춘 컴파일러를 사용하십시오. 여기서 "자격"은 규제 기관이 정한 표준에 따라 검증되었음을 의미합니다.
  2. 개체 코드 분석을 수행합니다.기본적으로 참조 코드 조각을 컴파일한 다음 출력을 수동으로 분석하여 컴파일러가 소스 코드를 역추적할 수 없는 명령을 삽입하지 않았는지 입증합니다.

당신은 Dijkstra가 쓴 것을 얻습니다.

Compcert C 컴파일러와 같이 공식적으로 검증된 컴파일러를 선택하세요.

  1. 컴파일러의 최적화 수준을 변경하면 출력이 변경됩니다.
  2. 함수를 약간 변경하면 컴파일러가 인라인되거나 더 이상 함수가 인라인되지 않을 수 있습니다.
  3. 컴파일러(예: gcc 버전)를 변경하면 출력이 변경될 수 있습니다.
  4. 특정 라이브러리 함수는 본질적일 수 있습니다(예: 최적화된 어셈블리 생성). 그러나 대부분은 그렇지 않습니다.

좋은 소식은 대부분의 경우 실제로 그다지 중요하지 않다는 것입니다.실제로 중요한 경우(예: ISR) 어셈블리를 고려할 수 있습니다.

눈에 띄는 결과를 생성하지 않는 예상치 못한 기계어 코드가 우려되는 경우 유일한 방법은 고객을 만족시킬 수 있는 일종의 인증을 위해 컴파일러 공급업체에 문의하는 것입니다.

그렇지 않으면 코드의 버그(테스트)에 대해 아는 것과 동일하게 알게 될 것입니다.

현대 컴파일러의 기계어 코드는 매우 다를 수 있으며 보잘것없는 인간에게는 완전히 이해하기 어려울 수 있습니다.

이 문제를 다음과 같이 줄이는 것이 가능하다고 생각합니다. 정지 문제 어떻게든.

가장 명백한 문제는 컴파일러와 그 결정론을 분석하기 위해 어떤 종류의 프로그램을 사용하는 경우 이를 어떻게 알 수 있다는 것입니다. 당신의 프로그램이 올바르게 컴파일되고 올바른 결과가 생성됩니까?

하지만 다른 "안전한" 컴파일러를 사용하고 있다면 잘 모르겠습니다.내가 확신하는 것은 처음부터 컴파일러를 작성하는 것이 아마도 더 쉬운 일이 될 것이라는 것입니다.

자격을 갖춘 또는 인증된 컴파일러라도 바람직하지 않은 결과를 낳을 수 있습니다.코드를 단순하게 유지하고 테스트하고, 테스트하고, 테스트하세요.사람의 실수를 허용하지 않고 손으로 기계 코드를 살펴보는 것입니다.PLus 운영 체제 또는 실행 중인 모든 환경(운영 체제 없이 프로그램만 사용하는 것이 좋음).

이 문제는 소프트웨어와 컴파일러가 시작된 이후 미션 크리티컬 환경에서 해결되었습니다.답글을 달아주신 많은 분들도 알고 계실 겁니다.각 업계에는 인증된 컴파일러부터 프로그래밍 스타일(항상 이런 식으로 프로그래밍해야 하며 절대 이런 식으로 프로그래밍해야 함), 많은 테스트 및 동료 검토에 이르기까지 고유한 규칙이 있습니다.모든 실행 경로 등을 확인합니다.

당신이 그러한 산업에 속해 있지 않다면, 당신은 당신이 얻는 것을 얻습니다.COTS 하드웨어의 COTS 운영 체제에 대한 상용 프로그램입니다.그것은 실패할 것입니다. 그것은 보장됩니다.

걱정이 되신다면 악의 있는 컴파일러의 버그 때문에 한 가지 권장 사항(IIRC, 일부 프로젝트의 NSA 요구 사항)은 컴파일러 바이너리가 코드 작성보다 먼저 작성된다는 것입니다.적어도 그런 사람은 아무도 없다는 걸 당신은 알겠죠 추가됨 대상으로 하는 버그 당신의 프로그램.

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