ASSERT와 Exception
2006/06/14 09:38
ASSERT
...는 내부 설계에 대하여 변수가 원하는 내용을 가지고 있는지 확인하는 데 사용한다. 라는게 사전적 의미이고 도대체 어디다 어떻게 써야 할지는 감이 안온다면 아래를 보자...

int GetLen()
{
    int size;
   ...
  return size;
}
int div(int a, int b)
{
  int c;
  c=a/b;
  return c;
}

void main()
{
    char *p;
    int size;
  int ans;

   ans = div(10,5);
 
size=GetLen();
    p=(char *)malloc(size);
    strcpy(p,"test");
    free(p);
}

1. div 함수
두수의 나누기를 위해서 div 라는 함수를 작성했다.
main 에서 div 함수를 호출하여 10을 5로 나눈 결과 값을 돌려받는다. 아무문제가 없어 보이는가?
만약 div(10,0)과 같이 함수를 호출한다면 에러가 발생할것이다.
div 내에서 0으로 나눌수 없도록 하는것도 중요하지만 div 라는 함수를 사용하는 개발자들이 올바른 인자를 넘겨야 하는것이 보다 중요하다.
여기서 우리는 div 함수 앞 부분에 ASSERT(b!=0); 이란 assert 조건을 추가 함으로써 div 라는 함수를 사용하는 다른 개발자들로 하여금 실수를 예방할수 있다.

2. GetLen 함수
GetLen 는 메모리 확보를 위한 길이 또는 크기를 돌려받는다.
만약 길이 또는 크기가 0으로 돌려받아졌을 경우는 어떻게 될까?
strcpy 또는 free에서 문제가 발생할 가능성이 많다.
이 또한 우리가 리턴 전에 ASSERT(size!=0); 을 추가하여 불분명한 버그에서 벗어날수 있다.

위의 2가지 예제로 모두 다 설명할수는 없겠지만 대략적으로 나마 ASSERT를 어디다 어떻게 써야할까의 막연함에서 조금이나마 탈피할수 있을것이다.
사실 ASSERT를 어디다 어떻게 쓰는냐는 ASSERT를 쓰냐 안쓰냐 만큼의 중요한 문제이다.

그 외에 좋은점으로....
버그발생지점을 정확하게 파악할수 있고,
협업에서 다른 개발자로 하여금 인수나 리턴값에 주의를 요하게 할수 있고,
개발 자체가 버그 테스트로 버그를 줄일수 있다.

주의사항
ASSERT내에는 가급적 하나의 조건식을 사용하고 릴리즈때 영향을 주는 코드 삽입 금지하도록 한다.
외부 데이터 입력 변수에는 사용하지 않는다.
메모리 할당 결과, 파일 열기 결과를 ASSERT 하지 않는다.
(파일이나 메모리의 할당 실패는 assert를 발생하는게 아니라 에러메세지 박스를 출력해서 사용자로 하여금 조치를 취하도록 해야 한다.)


EXCEPTION 예외
...란 의도한대로 프로그램이 진행되지 않고 다른 상황으로 흐름이 진행되는 상황을 할한다. 이런 예외가 발생했을때 적절한 조치를 취해줄 수 있는 절차를 구현하도록 문법을 정리해 놓은 것이 예외처리이다.

우리가 흔히 if 처리했던 작업들이고 또 if문으로도 충분히 처리할수 있는 작업들이다. 그럼 왜! 예외처리를 사용하는가? 아래를 보자...

예외처리를 하지 않은 경우...

void main()
{
    int x,y,r;

    printf("x 좌표 입력 : ");scanf("%d",&x);
    if (x < 0) {
         printf("%d는 음수이므로 잘못된 값입니다.\n",x);
         exit(-1);
    }
    printf("y 좌표 입력 : ");scanf("%d",&y);
    if (y < 0) {
         printf("%d는 음수이므로 잘못된 값입니다.\n",y);
         exit(-1);
    }
    printf("숫자 입력 : ");scanf("%d",&r);
    if (r < 0) {
         printf("%d는 음수이므로 잘못된 값입니다.\n",r);
         exit(-1);
    }

    gotoxy(x,y);
    printf("%d의 제곱근은 %.4f입니다\n",r,sqrt(r));
}

예외처리를 한 경우...

void main()
{
    int x,y,r;

    try {
         printf("x 좌표 입력 : ");scanf("%d",&x);
         if (x < 0) throw x;
         printf("y 좌표 입력 : ");scanf("%d",&y);
         if (y < 0) throw y;
         printf("숫자 입력 : ");scanf("%d",&r);
         if (r < 0) throw r;
    }
    catch(int a) {
         printf("%d는 음수이므로 잘못된 값입니다.\n",a);
         exit(-1);
    }

    gotoxy(x,y);
    printf("%d의 제곱근은 %.4f입니다\n",r,sqrt(r));
}

코드가 직관적이고 놀랄만하게 코드가 읽기 쉬워졌다. 프로그램의 안정성과 유지, 보수의 편의성은 증가하지만  프로그램이 비대해지고 느려지는 반대 급부를 쉽사리 무시할 수는 없다.


2006/06/14 09:38 2006/06/14 09:38
Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다