소개
MISRA-C 가이드라인은 영국 자동차 업계의 노력으로 1998년에 처음 등장했다. MISRA-C는 자동차 산업에서 소프트웨어에 대한 의존성이 급격하게 증가함에 따라 그에 대한 대안으로 인식되었다. MISRA-C는 현재 전 세계적으로 다양한 산업에서 C언어에 대한 코딩 표준으로 가장 널리 사용되고 있다. 첫 번째 버전인 MISRA-C : 1998(이하 “MC1”)이 업데이트 되어서 MISRA-C : 2004(이하 “MC2”)가 발행되었고, 이제는 2013년 3월 세 번째 버전인 MISRA-C : 2012(이하 “MC3”)가 자리하게 되었다.
이미 기존 버전의 MISRA를 준수하며 소프트웨어 개발에 많은 투자를 하고 있는 기업들이나, MISRA를 새롭게 접한 기업들은 이와 같이 질문할 것이다.
a) 새로운 코딩 규칙이 정말 필요한 것인가?
b) 새로운 코딩 규칙은 이전 버전의 규칙보다 월등히 좋아졌나?
c) 기존에 MC1/MC2를 준수한 Legacy 코드는 새로운 표준도 준수할 수 있을까?
본고는 MC3에 대한 간단한 요약과 함께 위와 같은 중요한 질문들에 대한 답변을 다룬다. 그리고 프로젝트 이면에 있는 동기부여, 이점, 그리고 새로운 표준을 준수하는데 예상되는 위험 요인들을 살펴본다.
C 언어는 진화하고 있다
이전 버전의 MISRA-C는 일반적으로 C90이라 알려져 있는 최초 C언어의 표준화된 버전을 따르도록 코드를 정의하였다. 이러한 보수적인 정책은 C99(1999년)와 C11(2011년)이 발간됨에도 불구하고 오랫동안 지속되어왔다.
C90에 대한 고수는 아래와 같은 최소 두 가지 중요한 이유 때문에 유지될 수 있었다.
a) 임베디드 C 산업분야에서 컴파일러 제조사들은 새로운 언어 기능의 구현이 천천히 진행된다. C90은 컴파일러들과 도구들에서 잘 지원되는 반면, C99와 C11에 추가된 기능들은 업체마다 지원하는 편차가 컸다.
b) C언어에 몇 가지 매력적인 기능이 새롭게 도입되었지만, 도입된 C언어의 기능들이 신뢰성 측면에서 검증된 것은 아니라는 견해가 일반적이었다. 새로 추가된 일부 기능은 기존의 C언어와 확연한 차이가 존재했고, 추가된 기능에서 계속적인 취약점들이 발표되었다. 이에 따라 새롭게 추가된 C언어의 기능에 대해 사람들은 의문을 품게 되었다. C언어 표준은 동작이 정의되어 있지 않은 항목(Undefined Behavior)들을 따로 정리하여 부록으로 제공을 하는데, C99는 C90과 비교하여 약 2배나 많은 정의되어 있지 않은 항목들을 가지고 있다.
표준화 프로세스에서 고민되는 점은 언어에 새로운 기능들을 추가하는 것은 매우 쉬운 반면, 현재 소스코드로 인한 동작변경 없이 기존 언어의 문제점들과 위험들을 제거하려는 것은 거의 불가능한 점이다. C언어는 수많은 장점을 가진 반면 여러 취약점이 존재한다. 그래서 코딩 규칙의 주요 목적 중 하나는 안심하고 사용할 수 있는 언어의 서브셋(Subset)을 구성하고 준수 함으로서 C언어의 취약점을 해결하는 것이다.
C언어는 여전히 많이 사용되고 있는 개발언어이며, 특히 신뢰성이 가장 중요하게 고려되는 Safety Critical 소프트웨어의 개발에서 지속적으로 비중있게 사용되고 있다. C99가 개발에서 확인된 이점들이 있었음에도 불구하고, MC3프로젝트의 초기 MISRA-C가 더 이상 C90의 형식 준수를 강요하지 않도록 결정하였다. MC3는 C99 기능 중에 inline함수와 _Bool 타입과 같은 기능이 상당히 가치있는 내용이라고 인정하였지만, 반대로 일부 C99 기능의 사용을 제한하는 11가지 새로운 규칙을 제시하였다.
개선사항
규칙의 정의(Rule Definition)
다양한 해석이 나오지 않도록 명확하면서도 모호하지 않게 코딩 규칙을 정의하는 작업은 상당히 어렵다. MISRA-C3에는 기존에 존재하는 룰이 서로 다른 해석으로 이해되지 않도록 많은 내용이 추가되었다. MISRA-C3에 정의된 코딩 규칙은 아래와 같은 내용을 포함하고 있다.
• Amplification – 코딩 규칙 요구 사항의 상세한 설명
• Rationale - 규칙이 필요한 이유에 대한 설명
• Exceptions - 규칙의 요구 사항이 적용되지 않는 특정 상황
• Examples - 준수 및 위반에 대한 코드 예제
용어(Jargon)
C언어의 기술적인 측면을 설명할 때, 반드시 ISO C표준에 포함되어 있고 명확한 의미를 가지고 있는 용어를 사용해야 한다. 그러나 코딩 규칙을 정의하는데 추가적인 용어 도입이 필요할 수 있다. 예를 들어, C언어에서의 “타입(type)”은 다양한 의미를 내포하고 있기 때문에 특히 문제가 된다. C언어에서 정의된 산술 표현의 “타입(type)”은 그 본질을 설명하기에 직관적이지도, 충분하지도 않다. 그래서 MC2에서는 “underlying type”과 “complex expression”의 개념이 소개되었다. 하지만 불행하게도 이러한 용어의 정의는 모호했고, 개념은 signed, unsigned 정수까지만 의미했다. 더 불행한 것은 “underlying type”용어는 C++언어에서 다른 의미로 사용되었고, “complex”용어는 일반적으로 C99에서 지원되는 대수(Algebra)인 “complex arithmetic”을 의미하는데 사용되었다.
그래서 MISRA-C3에서 “underlying type”은 “essential type”으로 대체되었고, “complex expression”은 “composite expression”으로 대체되었다. “essential type”은 코딩 규칙의 정의에서 산술 표현의 타입(type)을 설명할 때 더 직관적이다. MC3에서 “essential type”의 정의는 전체의 정수 타입(type)을 포함한다. 산술 표현의 타입(type)은 이제 다음 중 하나의 의미를 가진다.
• essentially Boolean
• essentially character
• essentially enum
• essentially signed
• essentially unsigned
• essentially floating
필수 규칙(Mandatory Rules)
MISRA-C의 이전 버전(MISRA-C 2004)은 두 가지 카테고리(Required Rules, Advisory Rules)로 룰을 분류 했다. 정식 예외(Formal Deviation)로 명시되는 항목이 아닌 이상, MISRA-C를 준수하도록 요구 받는 코드는 반드시 모든 “Required Rule”을 준수해야만 한다. “Advisory Rules”는 그보다 완화된 정도로 적용될 수 있고, 정식 예외(Formal Deviation)의 적용은 선택적으로 적용되었다.
중요도에 따라 코딩 규칙을 분류하는 것은 때로 주관적인 판단이 반영된다. 이 때 아래와 같은 다양한 요소들을 고려해야 한다.
a) 코딩 규칙의 위반이 소프트웨어 결함을 얼마나 발생시키는가?
b) 코딩 규칙의 위반이 얼마나 자주 발생하는가?
c) 코딩 규칙이 안전한 코드에 대하여 귀찮은(irksome) 제약사항을 요구하는가?
그러나 일부 코딩 규칙들은 예외(deviation) 없이 직관적이고, 명확하다. MISRA-C3는 그러한 규칙들을 Mandatory Rules로 분류한다. 그리고 이 규칙들은 어떤 상황에서도 예외(deviation)가 허용되지 않는다.
시행 가능성(Enforceability)
MISRA-C는 코딩 적용에서 정적 분석 도구의 적용을 강조해 왔다. 다음과 같은 이유로 자동 분석은 필수라고 인식 되어왔다.
a) 불확실성의 제거
b) 시간 절약
c) 코드를 개발할 때 빠르게 피드백 제공
d) 매뉴얼 코드 리뷰와 관련된 문제점 완화
실제로 정적 코드 분석은 단순한 코딩 규칙을 적용하는 것 외에 더 많은 역할을 의미한다. 코딩 규칙은 알려진 잠재결함을 줄일 수 있는 안전한 언어 서브셋(Subset)을 정의하는 것이다. 정적 분석 도구는 코딩 규칙의 적용뿐만 아니라 코딩 규칙에 의해 해결되지 않는 코딩 에러의 검출을 돕는다.
대부분의 코딩 표준에서 정적으로 실행 불가능한 규칙이 있다. MISRA-C2 내에 142개 규칙에서 약 9개의 규칙이 그러하다. 이러한 규칙을 준수하기 위해서는 아래와 같이 소스 코드에서 직접 해결할 수 없는 요구사항을 따라야 할 것이다.
a) 문서
b) 프로세스 요구사항
c) 막연하게 정의된 요구사항
d) 주석의 주관적인 해석
e) 기능 요구사항의 이해
예를 들면, Rule 12.10 “쉼표 연산자는 사용할 수 없다”와 같은 경우 소스 코드의 간단한 분석으로 완벽하게 코딩 규칙 위반을 점검할 수 있다. 반면에, 다음과 같은 규칙을 살펴보자.
a) Rule 2.4 : 코드 부분은 주석처리 하지 않아야 한다.
b) Rule 3.2 : 문자 집합(character set) 과 관련된 인코딩은 문서화되어야 한다.
c) Rule 18.3 : 하나의 메모리 영역은 관련 없는 목적을 위해 재사용하지 않는다.
이와 같은 규칙 준수는 소스 코드 분석과 관련되어 있지 않거나 불충분하기 때문에, 자동 분석에 의존할 수 없다.
MISRA-C3은 “규칙(rules)”과 “지침(directives)” 이라는 용어로 구분하며 다음과 같이 설명되어 있다.
“지침(directive)은 규칙의 준수여부를 확인하기 위해, 코딩 규칙 문서에서 충분한 설명이 없는 경우 참조하는 가이드라인이다. 검사를 수행하기 위해서 설계 문서 또는 요구 사양에 대한 정보가 추가로 필요할 수 있다. 정적 분석 도구는 지침 준수 확인에 확실히 도움이 될 수 있지만, 일부 어던 도구들은 전체적으로 본래의 뜻과 다르게 해석할 수 있으니 매우 조심해야 한다.”
“규칙(rule)은 요구사항에 대하여 자세한 설명이 제공되는 가이드라인이다. 규칙은 다른 정보 필요 없이 소스 코드가 규칙을 준수하는지 확인할 수 있어야 한다. 특히, 정적 분석 도구 규칙의 준수(Compliance)를 검사할 수 있어야 한다.”
범위와 준수(Scope and Compliance)
코딩 규칙의 적용 용이성은 규칙들 마다 상당히 다르다. 아주 간단한 규칙(e.g. “8진수 상수는 사용될 수 없다.”)들은 간단하게 한문장의 문법을 검사하는 것으로 수행될 수 있다. 하지만 다른 규칙들은 하나의 제어구문, 함수 전체, 하나의 전처리 파일단위(Translation Unit), 심지어 전체 프로젝트 단위로 분석이 요구된다.
규칙 준수(Compliance) 검증이 요구되는 분석에서, 분석의 범위를 설정하기 위해, MISRA-C3에 있는 모든 규칙들은 “System Rule” 또는 “Single Translation Unit Rule”로 분류된다. 이 구분은 2가지 이유 때문에 중요한 의미를 갖는다.
a) 하나의 전처리 파일단위(Translation Unit)의 내부에서 규칙을 준수했다고 해서 System Rule을 준수했다고 주장할 수 없다. System Rules 준수는 전체시스템의 단위로 인정 받을 수 있다.
b) System Rule을 준수하는 것을 확인하는 작업은 종종 상당히 많은 시간이 요구된다.
결정 가능성(Decidability)
코딩 규칙의 특성 중에서 중요한 특성은 결정 가능성(decidability)이다. 그것은 코딩 규칙 적용 도구의 능력마다 다르다고 알려져 있다. 위에 기술한 것처럼 어떤 규칙은 분석 단계가 간단하기 때문에 쉽게 분석될 수 있다. (문법 단계에서 표면적인 분석이 요구되는 정도) 그 외 다른 규칙들의 적용은 매우 깊은 단계의 코드 구조와 의미 분석이 요구된다.
하지만 일부 코딩 규칙은 본질적으로 결정이 불가능(undecidable)하다. 이는 아무리 정교한 도구가 분석한다고 해도, 규칙 준수에 대하여 절대 보증될 수 없음을 의미한다. 결정 가능한 규칙이란, 거짓 탐지(False Positive) 없이 어떠한 상황에서도 도구를 통해 규칙 위반 규명이 가능한 것을 말한다. 다른 말로 분석 도구가 어떤 상황에서 다음의 2개의 대답 중 하나가 가능한 것이다.
1. Yes – 규칙 위반은 분명히 이 시점에서 발생한다.
2. No- 규칙 위반은 분명히 이 시점에서 발생하지 않는다.
MISRA-C3에 있는 모든 규칙들은 명확하게 “decidable” or “undecidable”로 분류 된다. 143개의 Rule 중 28개가 “undecidable”로 분류된다. “undecidable” 일 때 절대로 준수를 보장할 수 없다. 규칙이 “undecidable”일 때 도구로부터 얻을 수 있는 최선의 진단은 다음의 형태가 될 수 있다.
3. 규칙 위반이 발생 가능하지만 항상 위반하는 것은 아니다.
사실 분석 도구들마다 “decidable” 규칙을 포함한 모든 경우에 대하여 효과적이고 정확하게 위반사항(또는 위반의 가능성)을 진단하는 능력들이 다르다.
마이그레이션(Migration)
MC2를 준수하여 개발된 코드에서 MC3의 영향은 무엇일까? 비록 MC3가 C99에 관련된 새로운 이슈를 해결하는데 목적이 있어도, 여전히 C90을 위한 환경에서 개발된 코드에 적합성은 유지되고, MC3에서 추가적으로 소개된 요구사항도 MC2를 준수한 코드에는 영향이 제한적이다.
아래의 제약 사항의 경우 코딩규칙의 신뢰성은 훼손될 수 있다.
- 알려진 소프트웨어 결함을 바로 지적하지 않은 경우
- 규칙을 회피하는 것이 더 큰 문제를 야기시키는 경우
- 완벽하게 안전한 코드를 위해 너무 많은 제약을 가하는 경우
MC3에서 개선사항들은 일부 코딩 제약사양을 가하는 경우 경감(완화)시킨 결과이다. 일부 규칙은 수정되었고 몇몇은 완전히 제거되었다.
결론
MISRA-C3은 MISRA-C2 비해 현격하게 문서의 양이 많지만, 전체 규칙 수는 많이 증가하지 않았다. MISRA-C2가 142개의 규칙을 갖고 있고 MISRA-C3는 143개의 규칙과 16개의 지침으로 구성되어 있다. 추가적으로 새로운 규칙들이 도입되었고 많은 규칙이 수정되었다. 그리고 일부는 삭제 되었다. MC3문서는 추가 요구사항의 결과보다, 개선의 결과로 인해 많이 늘어났다. 핵심 개선 내용은 아래와 같다.
- 개선된 규칙의 설명 : 부연 설명을 포함한 원인, 예외와 예제
- 규칙과 지침의 구분
- Mandatory 규칙의 분류
- 시스템 전체 단위 준수와 Unit 한 개 단위 준수의 구분
- 결정 가능성(decidability)에 대한 인식
MC2를 준수하여 Compile 되는 코드에서 새로운 표준의 영향은 제한적일 것이다.
잘 알려진 것처럼 Coding 표준의 내용은 논란을 일으킬 수 있는 주제이다.
MISRA도 이것을 피할 수 없지만, 여전히 준수할 수 있는 안전한 C언어의 서브셋(Subset)을 수립하는 것이 초미의 관심사이므로 광범위하게 선택되어 보편화가 되었다. MC3에서 결정가능성이 있는 것으로 분류되는 규칙비율은 매우 높고 중요하다. 그것은 MISRA-C 규칙의 분석을 지원하는 컴파일러와 정적 분석 도구의 표준 요구사항이 되고 있다.
저자에 대하여
Paul Burden은 PRQA에서 근무하는 Technical Consultant 이며 MISRA-C Working Group 이 설립된 10년 이상 동안 중요한 멤버로 활약해 왔다. 그는 Global 기업 고객에게 Coding Standards 준수에 대한 자문 및 교육을 진행하였다. 또한 QA•C의 제품 MANAGER로써 오랫동안 정적 분석 도구의 적용과 장점에 대한 많은 경험을 가지고 있다.
About PRQA
1985년 설립 된 PRQA는 정적분석 산업분야 개척자로, 결함 검출과 코딩 표준 자동검사 도구의 리더로, 소프트웨어 Inspection 과 코딩 룰 적용 기술의 주도기업으로 전문적인 기술력을 인정받았다.
PRQA의 산업 리딩 도구인 QA•C, QA•C++ 와 QA•Verify는 C 와 C++에서 가능한 최선의 시험을 할 수 있도록 한다. 강력하고 독자적인 구문 분석 엔진은 매우 정확한 언어 분석 및 이해력을 가졌으며, 깊고 정확한 Data Flow 기능과 결합되었다. 결합된 분석엔진을 통해 유지보수의 어려움, 위험, 복잡, 중첩, 이식불능 등 언어사용에 의해서 발생되는 여러 문제들을 식별하며, Coding 표준의 준수를 위한 수행방안을 제공한다.
PRQA는 MISRA-C:1998, MISRA-C:2004, MISRA-C:2012 또한 MISRA-C++:2008 의 Compliance Module을 공급한다. PRQA 도구의 효과는 다양한 시장에서 사실상 표준과 같이 사용된다. TERA-Labs(a research division of the Karel de Grote University College, Antwerp, Belgium)에서 독립적으로 수행한 연구조사 결과의 요약은 아래 링크에서 참고 하기 바란다.
www.programmingresearch.com/resources/white-papers/.
<저작권자 © AEM. 무단전재 및 재배포, AI학습 이용 금지>