본문 바로가기

C

c++ exception safety guarantee, exception 주의점, exception을 사용하지 말아야 하는 case

Exception Safety guarantee에는
1. Basic Exception Safety
2. Strong Exception Safety
3. No-throw guarantee가 있다.

 

Basic Exception Safety는 단순하게 exception 처리만 해준 것이다.

exception이 발생했음에도 불구하고,  다른 변수가 변경될 수 있다.

Strong Exception Safety는 Exception 처리로 다른 변수가 아예 변하지 않는다.

No-throw guarantee 는 Exception 처리가 다른 함수로 넘어가지 않고, 원래 함수에서 끝나는 경우이다.

 

그리고 Swap, destructor, move에는 exception 처리를 하지 말자.

그리고 noexcept를 붙이도록 하자. (컴파일러가 컴파일 시 최적화 함)

 

Exception을 사용하지 말아야 하는 경우

// Google은 Exception을 사용하지 않는다.
// Exception은 별도로 Object를 생성하기 때문에
// 추가적인 Resource를 생성하여 overhead가 발생한다

// Forloop 같은 regular error report
// 자체적으로 에러를 처리 가능한 internal error handling에는
// Exception을 사용하지 않아도 좋다.

// nullptr, out of range 에러는 bug이므로 exception을 사용하기 보다는
// 코드를 고치자
// 절대 일어나지 않을 일에 굳이 exception을 넣지 말자

 

Exception을 사용해도 좋은 경우

// 서버에서 packet을 받았는데 exception을 찍는다
// 파일을 읽었는데 파일이 없는 경우

코드 >>

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>
#include <exception>
// Exception Safety guarantee
// 1. Basic Exception Safety
// 2. Strong Exception Safety
// 3. No-throw guarantee
 
// Swap, destructor, move, default constructor는 
// Exception이 발생하면 c++ 프로그램이 꼬인다
// No except를 꼭 붙이도록 하자
 
int g = 0;
 
class Cat {
private:
public:
    Cat() { std::cout << "cat is created" << std::endl; }
    //Memory Leak 발생
 
    ~Cat() { std::cout << "cat is deleted" << std::endl; }
};
int divide(int a, int b)
{
    if (b == 0)
    {
        throw std::runtime_error("divide by 0");
 
    }
    return a / b;
}
 
void f()
{
    //Memory Leak 발생
    Cat* cp = new Cat();
    divide(100);
    delete cp;
}
 
 
// Basic Exception Safety
void f1()
{
    // Basic Exception Safety만 준수함
    // Memory Leak은 발생하지 않지만 프로그램의 상태는 변경됨
    g = 1;
    divide(100);
}
 
// Strong Exception Safety 준수
void f2()
{
    
    int a = divide(100);
    int b = divide(100);
    int c = divide(100);
    int d = divide(100);
 
    g = 1;
}
 
// No-Throw Guaruntee 준수
// 에러가 함수 밖으로 전달되지 않음
 
void f3()
{
    try 
    {
        int a = divide(100);
        int b = divide(100);
        int c = divide(100);
        int d = divide(100);
    }
    catch (const std::exception& e)
    {
 
    }
    g = 1;
}
int main()
{
    std::cout << "g : " << g << std::endl;
    try
    {
        f();
    }
    catch (const std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
 
 
    try
    {
        f1();
    }
    catch (const std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
    // program 의 state 변경
    std::cout << "g : " << g << std::endl;
 
    return 0;
}