C++异常处理机制的弊端

Posted by admin on 2019-12-25

C++异常处理机制的弊端

C++是C语言的升级版,引入了很多高级语言特性,其中就包括异常处理机制。
跟其他语言类似,C++使用try catch throw关键字处理异常。一个简单的C++异常处理程序,类似这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;

double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}

int main () {
int x = 50;
int y = 0;
double z = 0;

try {
z = division(x, y);
cout << z << endl;
} catch (const char* msg) {
cerr << msg << endl;
}

return 0;
}

看起来非常不错,异常被捕获了。编译运行该程序

1
Division by zero condition!

尽管预定义了很多标准异常,但是,现实中面对复杂业务场景,异常处理变得很蹩脚。
先看下面这个我根据真实的案例模拟的小程序

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
#include <iostream>
#include <exception>
using namespace std;

struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
struct MyException2 : public exception {
const char * what () const throw () {
return "C++ Exception2";
}
};
struct MyException3 : public exception {
const char * what () const throw () {
return "C++ Exception3";
}
};

void efun1()
{
throw MyException();
}

void efun2()
{
throw MyException2();
}
void efun3()
{
try{
efun1();
efun2();
}catch(...)
{
throw MyException3();
}
}

void efun()
{
try {
efun3();
}catch(...)
{
throw;
}
}
int main() {
try {
efun();
}
catch(std::exception& e) {
//Other errors
std::cout << "Std Exception caught" << std::endl;
std::cout << e.what() << std::endl;
}
}

其中,efun3 调用efun1,efun2 会抛出MyException3(). 那么main调用efun3所捕获的异常将是MyException3(), 而不是efun1异常MyException1()。 也就是说,MyException1被MyException3覆盖了。
你可能会说,efun3 不应该抛出自己的异常,只需要catch什么就throw什么。 这当然可以解决部分问题。但现实的场景往往是复杂的,

1
2
3
4
5
6
7
8
9
void efun3()
{
efun1();
//some IO operation
efun2()
//memory allocation..
...
//call 3rd-party api
}

可见,为了完美捕获异常,代码作者需要非常小心,而且可读性变差。而维护代码的代价也是不小。所以,干脆不要使用异常处理。

C++不使用异常处理

因为已经有谷歌背书,所以我说话的底气也足了。谷歌C++代码规范
关于构造函数异常的处理,并不是问题。你没必要非得在构造函数里面干那些抛异常的事情。
当然没了异常处理,你的log 和 error code也需要好好设计才是。