Contents
1. 참고도서 [Bottom] [Top]
- C++ 기초 플러스 제3판
- Stephen Prata 저, 이도희 역, 성안당
ISBN: ISBNKOka:8931546289
2. 주요 문법 [Bottom] [Top]
try { // 명령문 } catch( 예외 ) { // 예외 처리 명령문 }
try 블록은 예외가 발생할 코드 블록으로 그 뒤에 예외 처리를 위한 하나 이상의 catch 블록이 있어야 한다.
throw 예외;
throw 문으로 예외를 전달한다.
함수원형 throw( 예외1[, 예외2, ...] ); // 다수의 예외 지정 가능 함수원형 throw(); // 예외를 전달하지 않음
함수 원형과 함수 선언시 throw() 문을 지정하면 전달될 예외를 지정할 수 있다. 예외를 지정하지 않고 throw() 문만 사용할 경우 예외를 전달하지 않는다.
2.1. 그 밖에 옵션들 [Bottom] [Top]
catch(...) // 모든 예외 처리 { // 명령문 }
모든 예외를 처리할려면 생략 부호 ( ... ) 를 사용한다.
catch( 예외 ) { throw; // 예외 전달 }
상위 try ~ catch 블록으로 예외를 전달해야할 경우 throw 문만 사용한다.
2.2. 객체로 예외처리하기 [Bottom] [Top]
예외 정보를 객체로 전달할 경우 참조에 의하여 전달하는 것이 좋다. C++ 의 throw-catch 메커니즘이 함수의 인수 전달 방식과 비슷하기 때문에 참조에 의한 전달 방식이 가능하다.
1 //////////////////////////////////////// 2 // 예외 클래스 3 class CException 4 { 5 ... 6 }; 7 8 //////////////////////////////////////// 9 // 함수 원형 선언 10 int func() throw( CException & ); 11 12 //////////////////////////////////////// 13 // 예외 처리 14 try 15 { 16 ... 17 func(); 18 ... 19 } 20 catch( CException & e ) // 예외 포착 21 { 22 ... 23 } 24 25 //////////////////////////////////////// 26 // 함수 구현 27 int func() throw( CException & ) 28 { 29 ... 30 throw CException; // 예외 전달 31 ... 32 }
3. exception 클래스 [Bottom] [Top]
C++ 에서는 언어 차원에서 예외 처리를 포함 시키고 있다. 그 예로 exception 클래스는 다른 예외의 Base 클래스로 정의되어 있다. 또한 프로그램 코드에서는 exception 객체를 전달하거나 다른 exception 클래스의 Base 클래스로 사용할 수 있다.
#include <exception> using namespace std; class exception { public: exception() throw(); exception(const exception& rhs) throw(); exception& operator=(const exception& rhs) throw(); virtual ~exception() throw(); virtual const char *what() const throw(); };
3.1. what() 가상 함수 [Bottom] [Top]
virtual const char *what() const throw();
예외에 대하여 문자열을 반환하는 함수로 시스템에 따라 다른 문자열을 반환한다.
3.2. bad_alloc 예외 [Bottom] [Top]
exception 클래스를 상속한 클래스로 new 연산자를 사용하여 메모리 할당시 문제가 발생하면 전달되는 예외가 bad_alloc 예외 이다.
4. Unexpected exception [Bottom] [Top]
4.1. 처리 안된 예외 [Bottom] [Top]
지정된 예외 처리가 없을 경우 uncaught exception 에러 메세지가 표시되고 기본적으로 프로그램이 종료된다. 예외가 처리되지 않은 경우 다음과 같은 과정으로 프로그램이 종료된다.
- unexpected exception 에러 발생
- terminate() 함수 호출
- terminate() 함수에서 abort() 함수를 호출
- 프로그램 종료
4.1.1. 예외 처리 함수 변경 [Bottom] [Top]
typedef void (*terminate_handler)(); terminate_handler set_terminate(terminate_handler ph) throw(); void terminate();
set_terminate() 함수로 terminate() 함수를 설정할 수 있다.
4.2. 예상하지 못한 예외 [Bottom] [Top]
예상하지 못한 예외란 예외 처리가 없는 함수에서 예외가 발생하는 것과 같은 경우에 해당되며 처리 안된 예외와 비슷하게 처리된다.
- unexpected() 함수 호출
- terminate() 함수 호출
- terminate() 함수에서 abort() 함수를 호출
- 프로그램 종료
4.2.1. 예외 처리 함수 변경 [Bottom] [Top]
typedef void (*unexpected_handler)(); unexpected_handler set_unexpected(unexpected_handler ph) throw(); void unexpected();
set_unexpected() 함수로 unexpected() 함수를 설정할 수 있다.
4.2.2. unexpected_handler() 함수의 선택 [Bottom] [Top]
set_unexpected() 함수로 지정하는 함수의 동작은 set_terminate() 함수의 경우보다 더 정형화되어 있다. 특히 unexpected_handler() 함수는 다음과 같은 선택을 가지고 있다.
- terminate() ( 기본값 ), abort() 또는 exit() 함수를 호출하여 프로그램을 종료 시킬 수 있다.
- 예외를 전달할 수 있다. [[br]] 예외를 전달한 결과 ( 둘째 선택 ) 는 대체 함수 unexpected_handler 로 전달된 예외와 예외 지정에 달려 있다.
- 새로 전달된 예외가 예외 지정과 일치하면 프로그램은 거기서부터 정상적으로 진행한다. 즉, 새로 전달된 예외와 일치하는 catch 블록을 찾는다.
- 새로 전달된 예외가 예외 지정과 일치하지 않고 예외 지정에 std::bad_exception 형이 없으면 프로그램은 terminate() 를 호출한다. [[br]] bad_exception 형은 exception 형에서 유도되며 exception 헤더 파일에 선언되어 있다.
- 새로 전달된 예외가 예외 지정과 일치하지 않고 예외 지정에 std::bad_exception 형이 있으면 일치하지 않는 예외는 std::bad_exception 형의 예외로 바뀐다.
5. 예외를 사용할 때 주의할 사항 [Bottom] [Top]
- 예외 사용하면 프로그램의 크기가 커지고 속도가 떨어지는 경우가 있다.
- 예외 지정은 템플릿에 대해서는 잘 통하지 않는다. 왜냐하면 템플릿 함수는 사용된 전문화에 따라 서로 다른 종류의 예외를 전달할 수 있기 때문이다.
- 동적 메모리 할당에 대하여 주의하여야 한다.
5.1. 예: 동적 메모리 할당 [Bottom] [Top]
예외 처리시 객체의 경우 함수가 종료할 때 자동으로 객체가 제거 된다. 하지만 포인터 변수를 이용하여 할당된 경우 메모리 누수가 발생할 수 있다.
예1> 자동 객체 제거
1 void test1( int n ) 2 { 3 string mesg( "무한 루프" ); 4 ... 5 if( n == 10 ) 6 { 7 throw exception(); 8 } 9 ... 10 return; 11 }
예2> 메모리 누수
1 void test2( int n ) 2 { 3 char * mesg = new char( n ); 4 ... 5 if( n == 10 ) 6 { 7 throw exception(); // 메모리 누수 발생 8 } 9 ... 10 delete [] mesg; 11 return; 12 }
이런 경우 프로그래밍에 많은 주의를 기울려야 한다. 하지만 auto_ptr 템플릿을 이용하여 이러한 문제를 해결할 수 있다.
6. exception 헤더 파일 [Bottom] [Top]
namespace std { class exception; class bad_exception; typedef void (*terminate_handler)(); typedef void (*unexpected_handler)(); terminate_handler set_terminate(terminate_handler ph) throw(); unexpected_handler set_unexpected(unexpected_handler ph) throw(); void terminate(); void unexpected(); bool uncaught_exception(); };
