프로그램은 ‘버그(bug)’ / ‘오류(error)’ / ‘예외(exception)’에 의해서 멈추거나 종료되기도 한다. 세가지 단어를 구분하여 보자.
사전적인 의미
* bug : (컴퓨터 시스템이나 프로그램의)오류 * error : 오류 * exception : 예외
어느 저자의 정의
* bug : 프로그래머에 의한 프로그램 오작동 문제 ※ NULL포인터 호출, 배열 오버플로우, 동적메모리 미삭제로 인한 메모리 누수 등 * error : 사용자에 의한 프로그램 오작동 문제 ※ 할당된 크기보다 큰 문자열을 입력 * exception : 예상치 못한 error 발생에 의한 프로그램 오작동 ※ 연결이 종료된 디비에 접근, 손상된 파일에 접근 등
결론
* 프로그램에 문제가 있거나 예외처리가 되지않았을때 '오류가 발생했다.', '예외처리가 안됬다.'라고 표현된다. * 버그(bug)와 오류(error)를 궂이 나누자면 '프로그래머에 의한 버그', '사용자에 의한 오류'이다. * 예외는 프로그램 외적인 요인에 의해 발생하는 것이다.
프로그램 개발시에는 예외에 의해 비정상 작동이 일어나지 않도록 예외처리를 해주어야 한다. 그래야만 견고한 프로그램이 되고 사용자는 이를 믿고 사용할 수 있게 된다. 예외처리에는 다음 2가지 유형이 있다.
1. 반환 값을 사용한 예외처리
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 | #include "stdafx.h" #include <iostream> using namespace std; class MyException { public : MyException( int number) { this ->number = number; } int number; // >> 반환값을 사용한 예외처리 // 더큰수만 입력받는 함수 bool Test( int bigNumber){ if ( this ->number >= bigNumber) return false ; this ->number = bigNumber; return true ; } }; int _tmain( int argc, _TCHAR* argv[]) { MyException myException(100); bool isTrue = myException.Test(50); if (!isTrue) cout << "Error : 터큰수만 입력가능합니다.\n" ; return 0; } |
장점
* 간편히 구현이 가능하다.
단점
* 호출시 마다 반환값을 받아 비교해 에러를 알려야한다.
* 프로그램이 커진다면 소스코드에 예외처리 코드가 엉켜 지저분하다.
* 반환 값이 결과를 알리는 목적이기 때문에 다른 용도로는 사용이 불가하다.
2. try catch를 활용한 예외처리
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 | #include "stdafx.h" #include <iostream> #include <string> using namespace std; class MyException1 { public : MyException1(); MyException1( int code, string message){ this ->errorCode = code; this ->errorMessage = message; } int errorCode; string errorMessage; }; class MyException2 { public : MyException2() { cout << "여러가지 Exception이 가능합니다.\n" ; } }; class MyClass { public : MyClass( int number) { this ->number = number; } int number; void Test( int bigNumber){ if ( this ->number >= bigNumber) throw MyException1(100, "Error : 더큰수만 입력가능합니다.\n" ); if (bigNumber > 200) throw MyException2(); this ->number = bigNumber; } }; int _tmain( int argc, _TCHAR* argv[]) { // 기본적인 예외처리 try { MyClass myClass1(100); myClass1.Test(50); } catch (MyException1& ex) { cout << ex.errorMessage; } // 여러가지 예외상황을 고려할 수 있다. try { MyClass myClass2(100); myClass2.Test(201); } catch (MyException1& ex) { cout << ex.errorMessage; } catch (MyException2& ex) { cout << "Error : 너무 큰수를 입력하였습니다.\n" ; } return 0; } |
* 예외에 대하여 유연하게 처리할 수 있다.
* 여러예외를 잡아낼 수 있다.
* 예외 객체는 가능하면 참조로 받아 메모리 관리에 불편함이 없도록 하자.(MyException1& ex)
※ 객체로 받을 경우 불필요한 메모리 복사발생(MyException1 ex)
※ 포인터로 받을 경우 메모리 할당과 해제를 신경써줘야한다.(MyException1* ex)
* 여러 함수를 건너 사용할 수 있다.