코드 품질 향상을 위해 코드를 다듬다.(III)

코드 품질 향상을 위해 코드를 다듬다. 

 

코딩 규칙(Coding rule) 

다양한 임베디드 제품들은 일상 생활의 패턴을 변화시키고 있으며, 삶의 질과 편리성을 향상시키고 있습니다. 그러나 우리의 생활과 밀접해진 임베디드 제품들이 오동작을 한다면 매우 위험한 상황을 초래할 수도 있습니다.  특히 자동차, 철도, 항공, 원자력 발전소, 의료 장비 등과 같은 생명과 밀접한 기기들의 경우에는 안정성을 강조하는 것은 아무리 강조해도 지나치지 않을 것입니다. 이러한 맥락에서 임베디드 제품의 하드웨어 뿐만이 아니라 소프트웨어의 오류는 치명적인 위험을 초래할 것입니다.

코드 상에서 오류를 발생할 수 있는 경우에 대해 미리 확인하고 조치한다면 보다 안정적인 코드를 작성할 수 있습니다. 오류들을 사전에 미리 검토하여 수정하기 위해 코딩에 대한 규칙들을 만들어 사용하고 있습니다.  MISRA-C/C++, CERT C/C++ 등과 같은 대표적인 코딩규칙이 있습니다. 

영국의 자동차 산업 소프트웨어 신뢰성 협회(MISRA : Motor Industry Software Reliability Association)에서 1998년도에 “Guidelines for the use of the C language in vehicle based software” 라는 제목으로 MISRA-C:1998을 발표했습니다.  자동차에서 사용되는C언어 사용에 대한 가이드라인이 었으나,  2004년에 발표된 MISRA-C:2004에서는 “Guidelines for the use of the C language in critical systems”이라는 표제로 안전에 중요한 시스템으로 영역을 확장하였습니다. 이러한 MISRA-C:2004표준은 자동차 분야 뿐만이아니라 다른 산업군에서도 많이 사용되고 있습니다.  이 후  2013년에는 MISRA-C:2012를  발표하였습니다. 

안정성이 중요하게 요구되는 임베디드 시스템에서 이러한 코딩 규칙을 준수한 다는 것은 필수적이라고 볼 수 있습니다.  또한 현재의 IoT 기반의 임베디드 제품군들은 단순한 단독의 기기 동작이 아니라 다른 기기와의 통신들이 포함되어 있어, 이를 구현하기 위해서는  RTOS, 통신 스택(Communication stack), GUI와 같은 복잡한 코드가 포함될 수 밖에 없습니다. 코드의 양이 커질수록 오류에 대한 발생 빈도는 높아지고, 이를 해결하는데도 많은 시간이 소요됩니다.

실제로 코드를 작성하는데 발생될 수 있는 사항들을 살펴보면서 코드의 안정성과 품질을 높이는 방안을 고려해 보도록 하겠습니다.

먼저 공용체(union)에서 한 필드의 값을 다른 필드에 할당하는 경우에 발생될 수 있는 문제점입니다. 물리적으로 같은 영역의 개체 간에 한 개체의 값을 다른 개체로 할당하는 경우에는 정의되지 않은 동작이 발생할 수 있습니다.

다음의 예제에서 u.c[2]으 값을 u.i로 할당하는 경우에는 메모리에 값을 변경하면서 자신의 값도 변경이 될 수 있어 예상하지 못한 결과를 가져옵니다.

 

void example(void)

{

union

{

char c[5];

int i;

} u;

 

u.i = u.c[2];

}

 

앞의 예에서 살펴 보았듯이 동일 영역에서 사용되는 변수들의 경우에는 주의를 해야 합니다. 한 필드의 값을 다른 필드에 입력하는 과정에서 값이 변경될 수 있기 때문입니다. 다음의 예제처럼 값을 먼저 읽어 오고 보존해야 할 영역으로 입력해야 합니다.

   

void example(void)

{

union

{

char c[5];

int i;

} u;

 

int x;

x = (int)u.c[2];

u.i = x;

}

 

다음은 strcpy사용에 있어 발생할 수 있는 오류에 대해 살펴 보겠습니다.

함수 strcpy()에서 마지막에 NULL 문자가 포함되게 됩니다. 이러한 경우 할당한 버퍼의 크기가  충분하지 못한 경우에는 다른 영역의 메모리를 NULL값으로 변경하게 됩니다.

 

#include <string.h>

#include <stdlib.h>

void example(void)

{

char *str1 = "Hello World!\n";

char *str2 = (char *)malloc(13);

strcpy(str2,"");

strcat(str2,str1);

}

 

메모리 영역이 할당된 str2의 크기는 13 문자와 1문자의 NULL 값이 보관되어야 하므로 14바이트의 영역이 필요합니다.

다음과 같이 코드를 변경하여 메모리의 크기를 수정하여야 합니다.

 

#include <string.h>

#include <stdlib.h>

void example(void)

{

char *str1 = "Hello World!\n";

char *str2 = (char *)malloc(14);

strcpy(str2, "");

strcat(str2, str1);

}

 

작성한 코드에 대해 코딩 규칙에서 제시하는 사항들을 준수한다면 1차적인 오류 요소를 배제할 수 있습니다. 이러한 코딩 규칙에 대한 검사는 정적 분석 툴(static analysis)을 이용해야 확인이 가능합니다. 정적 분석 기능을 이용하여 미리 코드를 검토한다면 코드의 품질을 향상시킬 수 있습니다.

IAR Systems에서 제공하는 C-STAT 제품은 개발자들이 쉽고 편리하게 사용할 수 있도록 플러그인 방식으로 제공되고 있습니다. 이는 개발 작업의 흐름이 중단없이 진행될 수 있어 효율적인 개발 환경을 제공합니다.

감사합니다.

본 글은 IAR 시스템즈 코리아 기술팀 고성용 상무가 작성하였습니다.

© IAR Systems 1995-2018 - All rights reserved.