'예외처리'에 해당되는 글 1건

  1. 2010.01.08 C에서 goto를 이용한 예외처리 Macro들 1
"C 함수에서 2개의 return 문을 사용하게 제약한 코딩 스타일" 얘기한 함수 구조를 갖추기 위해서 예외처리 관련 매크로를 사용하고 있다.

이 예외처리 매크로는 goto 문을 이용하여 만들어 졌다. C로 구현된 매크로들을 Google에서 검색해보면 setjmp(), longjmp() 같은 것을 이용한 것들도 보이나, C 언어에서 제공되는 goto 만으로 만들어 사용하는 것이 이해하기 쉽고, 다양한 환경에서 무난하게 돌아가는 장점이 있다.

회사에서 사용하는 것보다 좀더 단순화시켜서 비슷하게 만들어 보겠다. C++이나 Java에서 사용하는 try { } catch { } 같은 스타일은 아니고, 크게 예외 판단 매크로들, 예외를 받는 매크로들로 구성이 된다.

직접 보는게 제일 이해가 빠를 것이다. 다음 프로그램은 "hello.txt"라는 파일에 "hello world"를 출력하는 프로그램이다.
[code c]/* * http://blog2.thewhiterock.net/ */ #include <stdio.h> #include <errno.h> #include "exception.h" int main(int argc, char **argv) { FILE *fp = NULL; int result = 0; fp = fopen("hello.txt", "w"); EXCEPTION_TEST_RAISE(fp == NULL, LABEL_OPEN_FAIL); result = fprintf(fp, "hello world\n"); EXCEPTION_TEST_RAISE(result < 0, LABEL_WRITE_FAIL); result = fclose(fp); EXCEPTION_TEST_RAISE(result != 0, LABEL_CLOSE_FAIL); return 0; EXCEPTION(LABEL_OPEN_FAIL) { (void)printf("Fail to open file 'hello.txt' ( %d )\n", errno); } EXCEPTION(LABEL_WRITE_FAIL) { (void)printf("Fail to write file 'hello.txt' ( %d )\n", errno); } EXCEPTION(LABEL_CLOSE_FAIL) { (void)printf("Fail to close file 'hello.txt' ( %d )\n", errno); } EXCEPTION_END; return -1; }[/code]

예외를 검사하는 EXCEPTION_TEST_RAISE() 매크로와 예외를 받는 EXCEPTION(), EXCEPTION_END 매크로들이 보인다. main() 함수의 구조를 보면 상단에는 주요 로직이 위치해 있고, 하단에는 예외 처리 로직이 위치한 형태를 가진다.

이 매크들이 구현된 것 또한 소스 코드를 직접 보는 것이 이해가 빠를 것이다. 다음은 exception.h 소스 이다.
[code c]/* * http://blog2.thewhiterock.net/ */ #ifndef __EXCEPTION_H__ #define __EXCEPTION_H__ #define EXCEPTION(label_name) \ goto EXCEPTION_END_LABEL; \ label_name : #define EXCEPTION_END \ EXCEPTION_END_LABEL: \ do \ { \ } while (0) #define EXCEPTION_TEST(expression) \ do \ { \ if (expression) \ { \ goto EXCEPTION_END_LABEL; \ } \ else \ { \ } \ } while (0) #define EXCEPTION_TEST_RAISE(expression, label_name) \ do \ { \ if (expression) \ { \ goto label_name; \ } \ else \ { \ } \ } while(0) #define EXCEPTION_RAISE(label_name) \ do \ { \ goto label_name; \ } while(0) #endif /* __EXCEPTION_H__ */[/code]