C 언어와 다르게, C++은 애러를 핸들링할 수 있는 try-catch
문을 제공합니다.
비교 | 조건문 if | 예외 처리 try-catch |
---|
핸들링 | return 값의 구분으로 핸들링 | throw 를 사용하여 catch로 분기 및 예외 처리 |
단점 | return 자료형에 종속적 | 반드시 try-catch 블럭에서 처리 |
조건문은 반환 값의 구분으로 핸들링하기 때문에 반환하는 자료형에 종속적입니다. 예를 들어 char getSome()
이라는 함수에서 예외 처리를 하고 싶은데 char
형으로 어떻게 구분을 지을 수 있을까요? NULL
값을 줄 수도 있지만 정말 NULL
을 반환한게 정상적인 흐름이라면 오류가 아닐텐데 말이죠!
⚠️ Warning
NULL 값을 반환하는게 정상일리는 없죠. 의도만 파악해주세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| #include <iostream>
#include <cstdlib>
#include <ctime>
char getSome()
{
srand(time(NULL));
char result;
char randomValue = rand() % 1000;
if(randomValue % 2 == 0)
{
// 정상
result = randomValue;
}
else
{
// 애러
result = '\0';
/*NULL을 반환함으로서 애러를 표현했지만
정상적인 경우에도 NULL이 나올 수 있음*/
}
return result;
}
int main(int argc, char **argv)
{
char value = getSome();
// NULL값도 정상인데? 처리할 방법이 없네!
if(value != '\0')
std::cout << value << std::endl;
return 0;
}
|
Usage#
위 극단적인 예시를 갖고 try-catch
를 사용하여 예외 처리를 해보겠습니다.
Example 📝#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| #include <iostream>
#include <cstdlib>
#include <ctime>
char getSome()
{
srand(time(NULL));
char result;
char randomValue = rand() % 1000;
if(randomValue % 2 == 0)
{
// 정상
result = randomValue;
}
else
{
// 애러
throw -1;
}
return result;
}
int main(int argc, char **argv)
{
try
{
char value = getSome();
std::cout << value << std::endl;
} catch(int e)
{
std::cout << "error:" << e << std::endl;
}
return 0;
}
|
- 18:
throw
를 이용하여 정상이 아닐 경우에 catch
로 -1
의 값을 던집니다. - 32:
-1
을 예외로 전달했기 때문에 int
자료형으로 인자를 받습니다. - 34: 예외 처리로 애러 코드를 console에 전달합니다.
또한 함수의 return
으로 구분하지 않아 자료형 선택이 자유롭고 더 나아가 특정 예외 처리를 위한 자료형도 만들 수 있습니다.
예외 처리를 위한 자료형은 어떻게 만들 수 있을까요? 애러 코드 및 메세지가 정의되어야 할 것이고, 간단히 콘솔 또는 파일로 출력해주는 함수가 있으면 좋을 것 같습니다.
코드와 메세지를 정의할 수 있는 변수와 출력을 하는 함수가 필요하므로 클래스로 만들어 볼 수 있습니다. CharException
이라는 클래스를 만들고 정의를 해보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| #include <iostream>
#include <cstdlib>
#include <ctime>
enum Error
{
NOT_MULTIPLE_TWO = -1
};
class CharException
{
private:
Error error;
public:
explicit CharException(Error e)
{
error = e;
}
void putLogToConsole()
{
std::string msg;
switch(error)
{
case(NOT_MULTIPLE_TWO):
msg.assign("is not multiple of two");
break;
default:
msg.assign("Unknown error");
break;
}
std::cout << msg << std::endl;
}
};
char getSome()
{
srand(time(NULL));
char result;
char randomValue = rand() % 1000;
if(randomValue % 2 == 0)
{
// 정상
result = randomValue;
}
else
{
// 애러
throw CharException(NOT_MULTIPLE_TWO);
}
return result;
}
int main(int argc, char **argv)
{
try
{
char value = getSome();
std::cout << value << std::endl;
} catch(CharException e)
{
e.putLogToConsole();
}
return 0;
}
|
- 5:
enum
키워드를 사용하여 애러 코드를 상수로 사용했습니다. - 10:
CharException
클래스, error 멤버 변수와 콘솔에 해당 애러 코드에 관한 메세지를 출력하기 위한 함수를 만들었습니다. - 55:
throw
에 기존 -1
대신 특별 예외 처리를 위한 자료형 CharException
클래스를 사용하여 catch
로 던집니다. - 69: 예외 처리에서는 콘솔에 메세지를 출력하는 함수를 이용하여 애러 메세지를 출력합니다.
⚠️ Warning
위 예시처럼 예외 처리 부분에 상세한 로그 내용(like stack trace)을 사용자에게 출력하는 행위는 보안상 안전하지 않습니다.
반드시 예외를 처리할 수 있는 로직이 올 수 있도록 작성해 주세요!
💡 Tips
이미 표준으로 정의되어 있는 Exception이 있습니다.
상세한 정보를 보시려면 여기를 참고하세요!
되도록 표준을 많이 사용하고 없는 경우 만들어 사용하면 될 것 같습니다.
성능 🚀#
try-catch
와 if
를 단순 비교했을 때 try-catch
가 더 많은 일을 수행하기 때문에 약간 뒤처진다고 합니다. 예외 처리가 되지 않을때는 if
와 성능차이 없음 따라서 실시간 처리를 요구하거나 높은 성능을 요구하는 시스템에서 부적절할 수 있겠으나, 개발자가 예상할 수 있는 에러를 핸들링할 수 있다는 점이 크기 때문에 사용하는 것 같습니다.
💡 자세한 내용은 이 곳에서 확인해주세요!