ë‚˜ì˜ ê²½ê¸°ëŠ” ìž ì—서 깨어난 순간부터 시작ëœë‹¤. --Reggie Jackson
 * ì›ë¬¸ë§í¬ :
http://www.cplusplus.com/doc/tutorial/tut5-3.html
http://www.cplusplus.com/doc/tutorial/tut5-3.html
1 시작하기 ì „ì— ì£¼ì˜ì‚¬í• #
ì´ ê°•ì¢Œì—서 설명하는 예외처리는 ANSI C++ í‘œì¤€ì— ì˜í•´ ì œì‹œëœ ê³µì¸ëœ 새로운 í‘œì¤€ì— ëŒ€í•œ ë‚´ìš©ì´ë‹¤. 만약 ì´ í‘œì¤€ì„ ì œê³µí•˜ì§€ 않는 컴파ì¼ëŸ¬ë¥¼ 사용한다면, ì´ ê¸°ëŠ¥ì„ ì‹¤ìŠµí• ìˆ˜ ì—†ìŒì„ ë°ížŒë‹¤. ì¼ë°˜ì 으로 컴파ì¼ëŸ¬ ìžì²´ì˜ 예외처리 ë¬¸ë²•ì„ ê°€ì§€ê³ ìžˆëŠ” 경우가 ë§Žê³ , ê·¸ê²ƒì„ ì‚¬ìš©í•˜ëŠ” ê²ƒì´ ë” ì¢‹ì„ ìˆ˜ 있다. Visual C++ì´ë‚˜ C++ Builder와 ê°™ì€ ìƒì—…ì 으로 ìœ ëª…í•œ 개발툴들과 g++ê³¼ ê°™ì€ íˆ´ì€ í‘œì¤€ 예외처리를 ì œê³µí•œë‹¤.
2 개요 #
í”„ë¡œê·¸ëž¨ì„ ê°œë°œí•˜ëŠ” 중ì—는, ì œëŒ€ë¡œ 실행ë˜ê³ 있는 코드ì¸ì§€ë¥¼ í™•ì‹ í• ìˆ˜ 없는 경우, ë˜ëŠ” 존재하지 않는 ìžì›ì„ ì–µì„¸ìŠ¤í•˜ë ¤í•œë‹¤ê±°ë‚˜, ì§€ì •í•œ 범위를 넘어서서 처리ë˜ëŠ” 경우등등과 ê°™ì€ ì¼ë“¤ì´ ìƒê¸¸ 수 있다.
ì´ëŸ° í˜•íƒœì˜ ë¹„ì •ìƒì ì¸ ìƒí™©ë•Œë¬¸ì— 예외처리를 사용하는 것ì´ë‹¤. C++ì€ ì´ëŸ° ìƒí™©ì— 대처하기 위해 3ê°€ì§€ì˜ ìƒˆë¡œìš´ ì—°ì‚°ìž(try, throw, catch)를 ì œê³µí•œë‹¤.
ì´ ì—°ì‚°ìžì˜ 대략ì ì¸ í˜•íƒœëŠ” 다ìŒê³¼ 같다.:
try {
// 예외가 ë°œìƒí• ì§€ 모르는 코드 부분
throw exception; // 예외가 ë°œìƒë˜ì–´ì•¼ í• ê²½ìš° 예외발ìƒ
}
catch (type exception)
{
// ê°ê°ì˜ ì˜ˆì™¸ì— ë”°ë¼ ì‹¤í–‰ë˜ì–´ì•¼ 하는 코드들
}
ê°ê°ì˜ ì—í• ë° ë™ìž‘ì€ ë‹¤ìŒê³¼ 같다:
- try 블ëŸë‚´ì˜ 코드는 ì •ìƒì 으로 실행ëœë‹¤. ë§Œì¼ ì§€ì •í•œ 블ëŸë‚´ì—서 예외를 ë°œìƒí•´ì•¼ í• ê²½ìš°, throw 키워드를 사용한다. throw í‚¤ì›Œë“œì— ë”°ë¥¸ ì¸ìžëŠ” ì–´ë–¤ ê²½ìš°ì— ëŒ€í•œ 예외ì¸ê°€ë¥¼ 나타낸다.
- 만약 예외가 ë°œìƒí•˜ê±°ë‚˜ throw 키워드가 실행ë˜ë©´, catch 블ëŸì´ ë°œìƒí•œ 예외를 나타내는 ì¸ìžì™€ 함께 실행ë˜ê²Œ ëœë‹¤.
// exceptions
#include <iostream.h>
int main () {
char myarray[10];
try
{
for (int n=0; n<=10; n++)
{
if (n>9) throw "범위를 벗어남!";
myarray[n]='z';
}
}
catch (char * str)
{
cout << "ì˜ˆì™¸ë°œìƒ : " << str << endl;
}
return 0;
}
ì´ ì˜ˆì œëŠ” for 루프안ì—서 nì´ 9ì´ìƒì´ ë˜ë©´ 예외가 throw하ë„ë¡ ìž‘ì„±ë˜ì–´ìžˆë‹¤. (왜ëƒí•˜ë©´, myarrayê°€ 10ê°œì˜ ì¸ìžë¥¼ 가진 배열로 ì„ ì–¸ë˜ì–´ìžˆìœ¼ë¯€ë¡œ ì¸ë±ìŠ¤ê°€ 9ì´ˆê³¼ì¸ ìˆ˜ê°€ ì§€ì •ë˜ë©´ ì ê·¼í• ìˆ˜ì—†ëŠ” 메모리를 억세스 하는 ê²ƒì´ ë˜ê¸° 때문ì´ë‹¤.) throwê°€ 실행ë˜ë©´ 루프와는 ìƒê´€ì—†ì´ catch 블ëŸë‚´ì˜ 코드가 실행ëœë‹¤. ê·¸ë¦¬ê³ catch ë¸”ëŸ ì•„ëž˜ê°€ 실행ë˜ê¸° 시작한다. (여기서는 그냥 0ì„ ë°˜í™˜í•œë‹¤.
throwì— ì˜í•´ ì‚¬ìš©ëœ ë¬¸ë²•ì€ ë§ˆì¹˜ return 키워드와 비슷하다. 단지 ( ) ë‚´ì— ë“¤ì–´ê°ˆ 수 있는 í˜•íƒœì˜ í•œê°œì˜ ê°’ë§Œì„ ì§€ì •í• ìˆ˜ 있다는 것만 기억해ë‘ìž.
catch 블ëŸì€ 반드시 try 블ëŸì— ì¸ì ‘해서 ì„ ì–¸ë˜ì–´ì•¼ë§Œ 한다. (둘 사ì´ì— 코드가 삽입ë˜ë©´ 안ëœë‹¤) catch ë¬¸ì´ ë°›ì•„ë“¤ì¼ ìˆ˜ 있는 ì¸ìžëŠ” ì–´ë–¤ ì 법한 íƒ€ìž…ë„ ìƒê´€ì—†ë‹¤. 여러 개를 ì§€ì •í• ë•Œì—는 catch는 서로 다른 íƒ€ìž…ì˜ ì¸ìžë¡œì„œ ì¤‘ì²©ì„ ì–¸ë 수 있다. ì´ëŸ° 경우는 try 블ëŸë‚´ì—서 해당 throw íƒ€ìž…ì— ë§žëŠ” catch 블ëŸë§Œ 실행ëœë‹¤:
// 예외처리 : 다중 catch 블ëŸ
#include <iostream.h>
int main () {
try
{
char * mystring;
mystring = new char [10];
if (mystring == NULL) throw "í• ë‹¹ 실패!";
for (int n=0; n<=100; n++)
{
if (n>9) throw n;
mystring[n]='z';
}
}
catch (int i) // 예외 1
{
cout << "예외 1 : ";
cout << "ì¸ë±ìФ " << i << " ë²ˆì€ ë²”ìœ„ë¥¼ 벗어난 것임!" << endl;
}
catch (char * str) // 예외 2
{
cout << "예외 2 : " << str << endl;
}
return 0;
}
위 코드와 ê°™ì€ ê²½ìš°ëŠ” ì ì–´ë„ 2ê°€ì§€ì˜ ì˜ˆì™¸ê°€ ë°œìƒí• ê°€ëŠ¥ì„±ì´ ìžˆë‹¤:
- 10ê°œì˜ ë¬¸ìžì— 대한 메모리가 í• ë‹¹ë˜ì§€ ì•Šì•˜ì„ ê²½ìš°(ê±°ì˜ ì¼ì–´ë‚˜ê¸° 힘들지만, ê°€ëŠ¥ì€ í•˜ë‹¤) : 예외 2ë²ˆì´ ë°œìƒí•œë‹¤.
- mystringì˜ ì¸ë±ìФ ì§€ì •ì´ ìµœëŒ€ì¹˜(9)를 ë„˜ì—ˆì„ ê²½ìš° : 예외 1ë²ˆì´ ë°œìƒí•œë‹¤.
try {
// 실행코드부분
}
catch (...) {
cout << "무언지 모르지만, 예외발ìƒ!";
}
It is also possible to nest try-catch blocks within more external try blocks. In these cases, we have the possibility that an internal catch block forwards the exception received to the external level, for that it is used the expression throw; with no arguments. For example:
try {
try {
// 실행코드부분
}
catch (int n) {
throw;
}
}
catch (...) {
cout << "예외발ìƒ!";
}
3 잡히지 ì•Šì€ ì˜ˆì™¸ì— ëŒ€í•œ 처리 #
만약 맞는 catch íƒ€ìž…ì´ ì—†ì–´ì„œ ì§€ì •í•œ catch ë¬¸ìž¥ë“¤ì— ëŒ€í•´ 예외가 잡히지 않았다면, 특별한 terminateë¼ëŠ” 함수가 실행ëœë‹¤. ì´ í•¨ìˆ˜ëŠ” ì¼ë°˜ì 으로 현재 프로세스를 ì¢…ë£Œí•˜ê³ , "Abnormal Termination"ì—러를 ì¶œë ¥í•œë‹¤. ê·¸ 함수 ì •ì˜ëŠ” 다ìŒê³¼ 같다:
void terminate();
4 표준 ì˜ˆì™¸ì˜ í™œìš© #
Some functions of the standard C++ language library send exceptions that can be captured if we include them within a try block. These exceptions are sent with a class derived from std::exception as type. This class (std::exception) is defined in the C++ standard header file <exception> and serves as pattern for the standard hierarchy of exceptions:
exception
- bad_alloc (thrown by new)
- bad_cast (thrown by dynamic_cast when fails with a referenced type)
- bad_exception (thrown when an exception doesn't match any catch)
- bad_typeid (thrown by typeid)
- logic_error
- domain_error
- invalid_argument
- length_error
- out_of_range
- runtime_error
- overflow_error
- range_error
- underflow_error
Because this is a class hierarchy, if you include a catch block to capture any of the exceptions of this hierarchy using the argument by reference (i.e. adding an ampersand & after the type) you will also capture all the derived ones (rules of inheritance in C++).
The following example catches an exception of type bad_typeid (derived from exception) that is generated when requesting information about the type pointed by a null pointer:
// standard exceptions
#include <iostream.h>
#include <exception>
#include <typeinfo>
class A {virtual f() {}; };
int main () {
try {
A * a = NULL;
typeid (*a);
}
catch (std::exception& e)
{
cout << "Exception: " << e.what();
}
return 0;
}
ì˜ˆì™¸ì— ëŒ€í•œ 표준 ìƒì† í´ëž˜ìŠ¤ë“¤ì„ ì‚¬ìš©í• ìˆ˜ ìžˆì„ ê²ƒì´ë‹¤. ì´ë ‡ê²Œ í•¨ìœ¼ë¡œì¨ ê°œë°œìžë§Œì˜ 예외를 ë˜ì§ˆ 수 있다ë˜ê°€, 새로운 예외ìƒí™©ì„ ìƒì†ë°›ì•„ 만들 수 있게 ëœë‹¤.
5 í™œìš©ìš©ë„ ë° ì •ë¦¬ #
예외는 C++ì˜ ê°•ë ¥í•œ 기능 중 하나ì´ê³ , 디버깅ì´ë‚˜ 다운ë˜ì§€ 않는 ë°©ì–´ì ì¸ í”„ë¡œê·¸ëž¨ì„ ì œìž‘í• ë•Œì— ìƒë‹¹ížˆ ê°•ë ¥í•œ ì—í• ì„ ìˆ˜í–‰í• ìˆ˜ 있다. 하지만, ê°œì¸ì 으로는 ìžì£¼ ì“°ì§€ ì•ŠëŠ”ë° ê·¸ ì´ìœ 는 다ìŒê³¼ 같다. (주관ì ì¸ ê²ƒìž„ì„ ë°ížŒë‹¤.)
- ë°©ì–´ì ì¸ ì½”ë“œë¼ê¸° 보다는 ì—러가 ìž ìž¬ë˜ì–´ìžˆëŠ” 코드를 뒷처리하는 ê²½ìš°ì— ì‚¬ìš©ë˜ëŠ” ê²ƒì´ ë³´í†µì´ì§€ë§Œ, ì´ëŸ° 경우 ê·¸ ì—러를 완벽하게 뒤처리 못하는 경우가 많다. 심지어 그냥 í”„ë¡œê·¸ëž¨ì„ ë¦¬ì…‹í• ê²½ìš°ê°€ ë§Žì€ë°, ì´ëŸ´ë•ŒëŠ” ì°¨ë¼ë¦¬ assertê°€ ë” íŽ¸ë¦¬í•˜ë‹¤.
- í”„ë¡œê·¸ëž¨ì„ ëª¨ë“ˆí™”í•˜ê¸° 힘들게 ëœë‹¤. 예외란 ê²ƒì€ ì–¸ì œë‚˜ ì¼ì • 코드ì˜ì—ì„ ì‹¸ê³ ìžˆëŠ” 형태를 취하므로, íŠ¹ì • í´ëž˜ìŠ¤ë“¤ì˜ ë§´ë²„í•¨ìˆ˜ë“¤ì— ê±¸ì³ì„œ ì¼ì–´ë‚˜ëŠ” ë²„ê·¸ê°™ì€ ê²ƒì—는 대처하기가 ìƒë‹¹ížˆ ì–´ë µë‹¤.
- ì½”ë“œëŸ‰ì´ ëŠ˜ì–´ë‚œë‹¤. (ë”°ë¼ì„œ 귀찮다. ^^) 게다가 ë‚˜ì¤‘ì— ì¼ì‹œì ì¸ ë²„ê·¸ë¡œ ë°í˜€ì¡Œì„ 때ì—는 쉽게 ê³ ì¹ ìˆ˜ 없다. (catchë¶€ë¶„ì˜ ì½”ë“œê°€ 아까워질 수 있다. -_-;)
- ë‚´ë¶€ì 으로 스íƒì„ 사용하므로 너무 중첩ì 으로 사용하면 곤란하다.
- 여러 예외가 중첩ì 으로 ì¼ì–´ë‚ 경우(tryë‚´ë¶€ì— ë˜ try...ì´ëŸ° ì‹ì¼ 경우) 잘못 작성하면 ì–´ëŠ ì˜ˆì™¸ê°€ ë°œìƒí–ˆëŠ”ì§€ì¡°ì°¨ 헛갈릴 수 있다. 다시ë§í•˜ë©´, 중급ì´ìƒì˜ 활용ì—서는 ì•½ê°„ì˜ íŠ¸ë¦ì´ 필요하다. (위 "표준 ì˜ˆì™¸ì˜ í™œìš©" 참조)
- íŠ¹ì • 소스ë¼ì¸ì´ 아닌 블ëŸë‚´ì—서 프로그램 ì‹¤í–‰ì´ ë©ˆì¶œì •ë„ì˜ ì—러가 ë°œìƒí• ê°€ëŠ¥ì„±ì´ ìžˆì§€ë§Œ, í”„ë¡œê·¸ëž¨ì´ ê³„ì† ì‹¤í–‰ë˜ì–´ì•¼ë§Œ í• ê²½ìš°ë¥¼ 들 수 있다. (0으로 나눌경우가 대표ì ì¸ ì˜ˆì´ë‹¤. ì´ë•Œì—는 1로만 ë°”ê¾¸ì–´ì¤˜ë„ ê·¹ë³µì´ ê°€ëŠ¥í•˜ë‹¤.)
- íŠ¹ì • ë¼ì´ë¸ŒëŸ¬ë¦¬ëŠ” 아예 ë‚´ë¶€ì 으로 예외를 ì •í•´ì„œ ì—러가 ë°œìƒí•˜ë©´ ê·¸ì— ë”°ë¥¸ 예외를 실행하ë„ë¡ ë˜ì–´ìžˆëŠ” 경우가 있다. (ACEê°€ 대표ì ì¸ ì˜ˆì´ë‹¤) ì´ë•Œì—는 예외를 공부해ë‘는 ê²ƒì´ ì¢‹ë‹¤.
- ìžì‹ ë§Œì˜ ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ ì œìž‘í• ê²½ìš°, 표준 예외를 ìƒì†í•´ì„œ 몇가지 예외를 ì„ ì–¸í•´ë‘ê³ í™œìš©í•˜ë©´ ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ 사용하는 쪽ì—서 íŽ¸ë¦¬í• ìˆ˜ 있다. 예외를 í´ëž˜ìŠ¤ë¡œ 줄 수 있다는 ê²ƒì€ ìƒë‹¹ížˆ ê°•ë ¥í•œ ê°œë…ì´ë¯€ë¡œ 확실히 알아ë‘는 ê²ƒì´ ì¢‹ë‹¤.








