[이미지=게티이미지뱅크]

[IAR 시스템즈=라파엘 토빈거(Rafael Taubinger)] 임베디드 업계는 복잡해진 소프트웨어를 점점 더 빠른 속도로 제공해야 한다는 문제에 직면했다. 이는 소프트웨어의 오류 위험을 증가시키고 제품 품질에 영향을 미치며, 보안 문제까지 발생시킬 수 있다.

동일한 결과값을 기대하며 소스코드를 재사용하거나 다른 아키텍처에서 마이그레이션하는 경우, 이러한 현상은 RISC-V 코드베이스에 더욱 현실적으로 나타난다. 그러나 대부분의 개발자들은 아키텍처, 새로운 명령어 세트, 소수의 확장자로만 이에 대한 대응을 시작하고 있다.

RISC-V 코드베이스 제어는 두 가지 실질적 측면에서 논의된다. 첫 번째는 향후 프로젝트를 위해 코드 기반을 재사용한다는 의미다. 두 번째는 코드 품질 불량은 사실상 널리 퍼져 있는 문제로, 잘못된 코딩 관행이 시스템의 취약함으로 직결된다는 주장이 여러 증거를 통해 이미 입증되어 있다는 것이다. 따라서, 모든 개발자와 회사가 오랜 시간이 지나도 소프트웨어가 여러가지 시험을 극복하고 결함이 존재하지 않거나 가능한 한 결함이 없는 수준으로 도달되도록 코드의 품질을 향상시켜야 한다는 점은 명확하다.

Boehm의 COCOMO 비선형 재사용 영향 방법. [이미지=IAR 시스템즈]
Boehm의 COCOMO 비선형 재사용 영향 방법. [이미지=IAR 시스템즈]

◆ 재사용 코드

Boehm의 코코모(COCOMO)는 재사용된 소프트웨어의 수정 정도에 따라 코드 작성의 상대적 비용의 영향이 얼마나 극적으로 변화하는지 추정하는 방법이다. X축은 재사용하려는 코드에 대한 수정 비율이고, Y축은 새로운 코드를 작성했을 때의 비율을 나타낸다. 코드의 3가지 데이터 샘플 중 2가지 샘플의 경우, 코드를 처음부터 다시 작성하는 노력의 50% 수준에 달할 만큼 재사용된 코드의 많은 부분을 수정할 필요가 없다.

코드를 재사용하고자 하는 경우, 코드를 높은 품질로 설계해 비용 효율성을 달성하는 것이 핵심이다.

◆ 코드 품질에 집중하기

RISC-V 설계 시 코드 품질에 집중해야 한다. 만약 개발 조직의 숙련도가 낮다면 최대 80% 시간을 디버깅에 할애해야 할 수도 있다. 공식적으로 빌드를 완료하기 전에, 결함을 신속히 격리할 수 있다면 개발 코드에 결함 주입 비율을 절감시켜 품질지표를 개선할 수 있다.

품질지표를 개선한 코드는 재사용할 만한 좋은 코드로 분류된다. 신뢰 가능하고, 새로운 버그가 발견될 가능성이 낮기 때문이다. 고품질의 코드는 관리가 용이하고, 코드도 쉽게 확장할 수 있어, 재사용 시 후속 프로젝트 역시 신속하게 진행 가능하다. 또한, 검증된 코드는 애플리케이션에 필요한 안전 인증을 받기 더 용이하다.

◆ 이용가능한 코딩 표준

이용가능한 코딩 표준은 많지만 사용되는 표준은 적다. MISRA C는 자동차 산업 소프트웨어 신뢰성 협회(Motor Industry Software Reliability Association, MISRA)에서 개발한 C 프로그래밍 언어용 소프트웨어 개발 표준으로, 임베디드 시스템, 특히 ISO C에 프로그래밍된 시스템 컨텍스트에서 코드의 안전성, 이식성, 신뢰성을 증진시키기 위해 개발됐다.

MISRA C 표준의 첫 번째 버전인 "차량 기반 소프트웨어에서 C 언어 사용 지침"은 1998년에 발행되었으며, MISRA C:1998로 공식적으로 알려져 있다. 더 많은 규칙을 추가하기 위해 2004년과 2012년에 업데이트됐으며, C++ 2003을 기반으로 하는 MISRA C++ 2008 표준도 있다.

MITRE의 CWE -공통적인 약점 열거 목록( Common Weakness Enumeration) 에서도 우수한 코딩 표준 규범을 몇 가지 확인할 수 있다. 해당 목록은 mitre.org의 유저들이, 개발자가 실수로 코드에 주입하게 되는 결함의 종류를 파악하기 위한 설문조사에서 시작됐다.

우리는 이 데이터를 통해 많은 개발자들이 같은 종류의 실수를 저지르는 경향이 있다는 것이 놀라운 점을 확인했다. 예컨대, C++ 코드(또는 C 코드에서도)에서 할당 해제 없이 할당되는 코드 등, 개발자가 피해야 하는 실수를 일반화한 CWE 목록이 등장했다. 또한 프로토타이핑 없이 사용되는 함수들도 존재하는데, 이는 코딩의 수준을 높이기 위한 흥미로운 시도다.

함수의 프로토타입을 작성하지 않을 경우, 컴파일 시 엄격한 유형 검사를 수행하지 않지만 C 언어의 규칙에 따르면 프로토타입이 없으면 모든 인수가 정수로 승격되기 때문에 코드 효율성이 떨어질 수도 있다. MCU에 FPU가 없을 경우, 캐스팅, 부동 소수점 연산을 호출할 수 있다. 따라서 항상 프로토타입을 만들어야 한다. 그러나 CWE의 주요 핵심은 위험하고 불량한 코딩 동작을 식별한다는 것이다.

SEI CERT C와 C++는 또한 범위를 벗어난 조건에 대해 부동소수점(float)을 확인하고 상수(const)를 재정의하지 않도록 하는 것과 같은 사례 연구에서 나오는 일반적인 취약점을 정의한다. 또한 코드의 가독성과 이해도를 높이기 위해 코딩 스타일에 관한 규칙을 규정한다.

◆ MISRA C 2012의 현실적인 사례

MISRA C 2012는 임베디드 애플리케이션에서 코드 품질을 확보하기 위해 널리 사용된다.

MISRA C 2012의 지침 4.6에서는 기본 데이터 유형을 사용할 수 없다. 컴파일러마다 크기와 부호 면에서 정수(int)와 같은 인수들을 취급하는 방법이 다르기 때문인데, 코드 리뷰가 까다롭다.

리뷰어가 해당 코드를 검토할 경우, 컴파일러가 해당 코드를 해석하는 방법을 코드 작성자가 이해에 어려움이 많다. 기본 유형을 사용하지 않으면 컴파일러와 아키텍처에서 코드가 불변(invariant) 상태가 된다.

너비와 부호가 변수 유형에 분명히 명시되어 있기 때문에, 개발자들은 대부분 컴파일러에 변수가 부호 없는 16비트 수 임을 알려주는 uint16_t같은 자료형을 사용한다. 이들은 stdint.h의 일부다.

또 다른 흥미로운 지시자는 규칙 13으로, AND 또는 OR 연산자의 우변에 함수가 실행됨으로써, 함수 외부에 존재하는 값이나 상태를 변경시키는 부수 효과(side effect)를 포함할 수 없다.

MISRA C 2012 - 규칙 13의 코드 예제. [이미지=IAR시스템즈]
MISRA C 2012 - 규칙 13의 코드 예제. [이미지=IAR시스템즈]

그러나 좌변의 표현식이 false인 경우에만 우변이 실행된다는 것이 중요하다. 그렇게 되어야만 포인터 p가 후위 증가(post-incremented)하게 된다. 이 때, 코드 작성 시에 이러한 동작이 잘못되기 쉬우며, 코드를 검토, 테스트 또는 유지, 관리하는 모든 사람들이 코드 작성 방법의 결과를 이해해야 한다는 것이 문제다. 이 코드 섹션의 주석을 통해, 이해관계자들에게 도움이 될 수 있다는 것은 분명하지만 현실적으로 제대로 문서화되지 못하고 있다.

흥미로운 좋은 사례로는, if 또는 while 문의 본문을 중괄호로 묶어야 한다는 규칙 14도 있다.

MISRA C 2012 - 규칙 14의 코드 예제.  [이미지=IAR시스템즈]
MISRA C 2012 - 규칙 14의 코드 예제.  [이미지=IAR시스템즈]

z=1 구문을 else 블록의 일부로 기능하도록 의도하였는지 여부를 판별하기는 어렵다. 이는 이전의 구문과 같은 수준에서 들여쓰기 되었기 때문에 발생한다. 의도적으로 z=1 구문을 else 블록의 일부가 되도록 한 경우, z=1 구문은 작성된 그대로 코드 블록에 들어가지 않기 때문에 버그가 나타난다. 해당 규칙은 이러한 유형의 코딩 오류를 방지할 수 있다. 이는 MISRA C에서 사용 가능한 200개 이상의 규칙 중 일부에 불과하며, 그 외의 다양한 규칙들과 함께 코드의 안정성과 이식성을 높여, 코드 설계의 실현 가능성을 보장한다.

◆ 더 좋은 코드를 구성하기 위한 신속한 방법

코드 품질을 향상시키는 가장 빠른 방법은 코드 분석 툴(code analysis tool)이다. 실제로 기능상의 안전을 인증하는 어플리케이션을 수행할 경우, 정적 분석을 사용해야 한다. 이러한 유형의 도구는 코드에서 가장 일반적인 결함 소스를 찾기 위해서 사용되며, 개발자가 코드 작성 시에 고려하지 못하거나 발생가능한 버그 등을 우려하지 않는 지점의 문제를 발견하고자 할 때에도 유용하고, 특히 개발자들이 구동을 위해 스캐폴드 코드를 올릴 때 효과적으로 사용된다.

정적 분석 솔루션의 품질에 따라, 컴퓨터 상에서 코드를 확인하는 동안 다른 많은 잠재 문제를 확인할 수 있다. C-STAT는 MISRA C 2004 및 2012 규칙 집합, MISRA C++ 2008 규칙 집합, 그리고 MITRE의 CWE 및 SEI CERT C에서 그에 합당한 규칙들을 제공한다.

표준과 규칙 선택. [이미지=IAR 시스템즈]
표준과 규칙 선택. [이미지=IAR 시스템즈]

카테고리 수준으로 드릴 다운하여, 프로젝트에 적용 가능하다고 생각되는 규칙만 선택할 수도 있다. 또한, 그룹, 파일, 기능 또는 개별 라인 수준에서 이러한 선택 사항을 재정의해, 검사 중인 대상에 대해 세부 수준을 완전히 제공할 수 있다. 도구가 구성되면 프로젝트(또는 그룹 또는 개별 소스 파일)를 분석할 수 있다.(또는 파일링할 수 있다). 분석 완료 후, 각 파일을 자세히 살펴보며 발생한 문제를 확인할 수 있다.

코드 분석 메시지. [이미지=IAR 시스템즈]
코드 분석 메시지. [이미지=IAR 시스템즈]

CERT-ERR33-C_c는 CERT C 규칙의 일부이며, 대부분의 규칙은 스스로 입증될 만한 자명한 규칙이다.

상황에 맞는 도움말. [이미지=IAR 시스템즈]
상황에 맞는 도움말. [이미지=IAR 시스템즈]

도움말 창에서 문제에 대한 전체 설명, 버그가 얼마나 확실한지, 버그가 나타날 경우 발생하는 심각도, 코딩 표준에 대한 모든 위반 사항을 확인할 수 있다.

도움말에서는 좋지 않은 사례를 예제로 제공한다. 1-3 코드 예제 등의 오류를 수정해 검사를 통과하고 코드를 더욱 강력하게 만드는 방법을 확인할 수 있다는 것이 중요하다. 이는 정적 분석을 통해 소스 코드에서 발견한 결함을 신속하게 근절하고자 할 때 유용하다.

실패 및 점검 통과 시의 코드 예제. [이미지=IAR 시스템즈]
실패 및 점검 통과 시의 코드 예제. [이미지=IAR 시스템즈]

◆ 자동화된 작업 흐름

코드 품질 보장은 매일 책상에서 일하는 개발자들에게 중요할 뿐 아니라, 버추얼 머신(Virtual Machines, VM) 컨테이너(Docker) 및 런너(Runners)를 포함한 CI/CD 파이프라인에 대하여, 현대적이고 확장가능한 빌드 서버 토폴로지에서 훨씬 더 중요하다. 코드 분석 툴이 높은 확장성을 갖추고 있어야만, 프로그래밍 표준 준수를 보장하는 자동화된 작업 흐름 완성이 가능하다.

리눅스 - 우분투의 명령 라인에서 사용되는 C-STAT 정적 분석 도구의 사용 사례를 도시하고 있다. 많은 자동화된 작업 흐름에서, 플랫폼 간의 지원은 개발팀의 효율성을 향상시키는 표준으로 기능한다.

자동화된 작업 흐름. [이미지=IAR 시스템즈]

◆ 코드 분석을 통한 도움 받기

분석 실행 중 시스템을 실행하지도 않기 때문에 시스템의 성능에 영향을 미치지 않는다는 것이 정적 분석의 이론적인 주요 또한 테스트 슈트의 품질과도 무관하다.

실행 중인 코드에서 특정 오류를 검색하는 것은 특정 데이터 세트에서 프로그램을 통한 특정 경로 실행에 의존한다. 정적 분석 툴은 이론적으로 코드를 통해 가능한 모든 경로를 검사할 수 있으며, 개발 사이클 초기에 코드 품질 관리를 도입하거나 코드를 재사용하고 소스 코드를 미리  검증함으로써, 오류의 영향을 최소화할 수 있다.

 

회원가입 후 이용바랍니다.
개의 댓글
0 / 400
댓글 정렬
BEST댓글
BEST 댓글 답글과 추천수를 합산하여 자동으로 노출됩니다.
댓글삭제
삭제한 댓글은 다시 복구할 수 없습니다.
그래도 삭제하시겠습니까?
댓글수정
댓글 수정은 작성 후 1분내에만 가능합니다.
/ 400
내 댓글 모음
저작권자 © 테크월드뉴스 무단전재 및 재배포 금지