抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

异常 exccpticn

异常处理

  1. 断言/if-else

​ assert()

​ 中断程序执行(直接中断不给修复的机会)

​ assert 报错只有程序能看懂的信息(数据结构的)对用户不是很友好

  1. 错误码

    sgrt(1) >= 0

  2. 异常(C++)

    try catch {} 在栈上寻找代码-> raise/throvo

c++异常

C++ 提供的异常类

1
2
#include <stdexcept>
#include <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
/*************************************************************************
> File Name: 1.tryCatch.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月21日 星期四 10时41分00秒
************************************************************************/

#include <iostream>
using namespace std;

int main() {

try {
// 可能含有异常的代码
cout << "throwing" << endl;
throw(1);
// 异常后,后面的代码就不会执行了
cout << "lalalala" << endl;

// ... 捕获全部异常
} catch (int &e) {
cout << "caught an integer" << endl;
} catch(...) {
cout << "exception caught" << endl;
}

return 0;
}

image-20220721111252297

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

// 定义一个自己的异常
class MyException : public runtime_error {

public :
// runtime_error 初始化父类异常
MyException(const string &s) : runtime_error(s) {
cout << "MyException ctor" << endl;
}
// noexcept 不会再抛出异常了
// 自定义异常信息
const char *what() const noexcept override {
return "123";
}
};

int main() {

try {
// 可能含有异常的代码
cout << "throwing" << endl;
throw(MyException("hello world"));
// 异常后,后面的代码就不会执行了
cout << "lalalala" << endl;

// ... 捕获全部异常 引用传递因为再向上传递时候可能会发生一些深拷贝的情况
} catch (runtime_error &e) {
cout << e.what() << endl;
} catch(...) {
cout << "exception caught" << endl;
}

return 0;
}

栈堆-异常

image-20220721123109500

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
106
107
108
109
110
111
112
113
114
115
116
/*************************************************************************
> File Name: 1.tryCatch.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月21日 星期四 10时41分00秒
************************************************************************/

#include <iostream>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

// 定义一个自己的异常
class MyException : public runtime_error {

public :
MyException(const string &s) : runtime_error(s) {
cout << "MyException ctor" << endl;
}
// noexcept 不会再抛出异常了
const char *what() const noexcept override {
return "123";
}
};

int main() {

try {
// 可能含有异常的代码
cout << "throwing" << endl;
throw(MyException("hello world"));
// 异常后,后面的代码就不会执行了
cout << "lalalala" << endl;

// ... 捕获全部异常
} catch (runtime_error &e) {
cout << e.what() << endl;
} catch(...) {
cout << "exception caught" << endl;
}

return 0;
}

ENDS(test1)


BEGINS(test2)

// 工具人
class Helper {

public :
/*
Helper(const char *s) {
// cout << this << s << " : Helper ctor" << endl;
}
*/

Helper() {
cout << this << " : Helper ctor" << endl;
}

~Helper() {
cout << "Helper dtor" << endl;
}

void boom() {
cout << "boom" << endl;
}

};

void inner() {

// Helper p1[3] = {Helper("p1"), Helper("p1"), Helper("p1")}; // stack 栈上 会呗自动析构掉 再抛出异常前就会析构掉
// Helper p1[3] = {"p1", "p1", "p1"}; // stack 栈上 会呗自动析构掉 再抛出异常前就会析构掉
// Helper *p2 = new Helper[3]{"p2", "p2", "p2"}; // 在堆上开辟析构函数就不会呗调用

// 只清理栈上内容 stack unwind 栈展开
Helper p1[3]; // stack 栈上 会呗自动析构掉 再抛出异常前 就会析构掉
Helper *p2 = new Helper[3]; // 在堆上开辟析构函数就不会 呗调用 内存泄漏

throw(1); // 向上去找栈上处理函数 main <- outer <- inner (没找到就向上找 完了会把本层清掉)
p1[0].boom();
}

void outer() {
try {
inner();
} catch(...) {
cout << "exception caught" << endl;
}
}

int main() {
outer();

return 0;
}

ENDS(test2)

int main() {
// 异常处理即自定义异常处理
// test1::main();

// 栈-堆
test2::main();

return 0;
}

函数调用过程

  1. 处理函数参数

    一般来所 (压栈)实现

  2. 将返回地址

​ 压栈

  1. 备份原栈帧

    压栈

  2. 开辟信栈帧

4种函数调用方式

  1. codecl (c++/c默认)
  2. stdcall
  3. fastcall
  4. 类(thiscall)

codecl

放参数(栈)、调用函数、清理参数

特点:参数放在栈上、参数由外层清理

汇编流程

  1. 向栈上反向push参数

  2. call调用(自动push返回地址)

  3. push ebp (备份原栈底)

  4. mov ebp, eso (提高栈底)

  5. sub esp, _ (提高栈顶)

  6. add esp, _ (恢复栈顶)

  7. mov esp, ebp (恢复栈顶)

  8. pop ebp (恢复栈底)

  9. ret 清返回地址并返回

  10. 在函数外清理参数

image-20220721145022201

image-20220721145149349

评论