Skip to content

Commit

Permalink
exception (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
chingchuanchen authored May 19, 2024
1 parent 55a0ef6 commit 63c76e1
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 0 deletions.
6 changes: 6 additions & 0 deletions day09/01reterr/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.2)
project(01reterr)

set(CMAKE_CXX_STANDARD 17)

add_executable(01reterr main.cpp)
33 changes: 33 additions & 0 deletions day09/01reterr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 错误与错误处理

* 何为错误
* 语法错误:程序员在编码阶段解决并通过编译
* 逻辑错误:程序员借助于调试工具诊断并修改
* 功能错误:程序员修改代码,测试员回归验证
* 设计缺陷:设计员修改设计,程序员重新编码
* 需求不符:分析员修改需求,设计员调整设计
* 环境异常:可以协助用户调整程序的运行环境
* 操作不当:客服知道用户按照正确的方法操作

* 错误处理主要针对在实际运行环境中发生,却在设计、编码和测试阶段无法预料的,各种潜在的异常

* 三种典型的错误处理机制
* 通过返回值返回错误信息
* 所有局部对象都能正确地被析构
* 逐层判断,流程繁琐
* 借助`setjmp/longjmp`远程跳转
* 一步到位,流程简单
* 某些局部对象可能因此丧失被析构的机会
* 抛出-捕获异常对象
* 形式上一步到位,流程简单
* 实际上逐层析构局部对象,避免内存泄漏










54 changes: 54 additions & 0 deletions day09/01reterr/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <iostream>
#include <cstdio>

using namespace std;

class A {
public:
A() {
cout << "A::A()" << endl;
}
~A() {
cout << "A::~A()" << endl;
}
};

int func3() {
A a;
FILE* fp = fopen("none.txt", "r");
if (! fp) {
cout << "fopen failed" << endl;
return -1; // return下一步到函数的右括号,它的指令就包括对局部变量的析构
}
// ...
fclose(fp);
return 0;
}

int func2() {
A a;
if (func3() == -1) {
return -1;
}
// ...
return 0;
}

int func1() {
A a;
if (func2() == -1) {
return -1;
}
// ...
return 0;
}


int main() {
if (func1() == -1) {
return -1;
}

return 0;
}

6 changes: 6 additions & 0 deletions day09/02jmperr/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.2)
project(02jmperr)

set(CMAKE_CXX_STANDARD 17)

add_executable(02jmperr main.cpp)
56 changes: 56 additions & 0 deletions day09/02jmperr/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <iostream>
#include <cstdio>
#include <csetjmp>

using namespace std;

jmp_buf g_env;

class A {
public:
A() {
cout << "A::A()" << endl;
}
~A() {
cout << "A::~A()" << endl;
}
};

void func3() {
A a;
FILE* fp = fopen("none.txt", "r");
if (!fp) {
// goto不能跨函数,即goto和escape要在同一个函数
//goto escape;
longjmp(g_env, -1);
}
// ...
fclose(fp);
}

void func2() {
A a;
func3();
}

void func1() {
A a;
func2();
}


int main() {
// 第一次调用setjmp会返回0,把当前栈帧存到g_env中
if (setjmp(g_env) == -1) {
cout << "fopen failed" << endl;
return -1;
}

func1();

return 0;

escape:
cout << "fopen failed" << endl;

}
6 changes: 6 additions & 0 deletions day09/03experr/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.2)
project(03experr)

set(CMAKE_CXX_STANDARD 17)

add_executable(03experr main.cpp)
59 changes: 59 additions & 0 deletions day09/03experr/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <iostream>
#include <cstdio>


using namespace std;

class A {
public:
A() {
cout << "A::A()" << endl;
}
~A() {
cout << "A::~A()" << endl;
}
};

void func3() {
A a;
FILE* fp = fopen("none.txt", "r");
if (!fp) {
throw -1;
// 1.跳转到当func3()的右括号
// 2.跳转到当func2()的右括号
// 3.跳转到当func1()的右括号
// 4.跳转到当try的右括号
// 5.在catch中有没有处理异常值的代码
}
// ...
fclose(fp);
}

void func2() {
A a;
func3();
}

void func1() {
A a;
func2();
}


int main() {
try {
func1();

// 不执行后面的代码
cout << "after exception" << endl;
}
catch(int ex) {
if (ex == -1) {
cout << "fopen failed" << endl;
return -1;
}
}

return 0;
}

0 comments on commit 63c76e1

Please sign in to comment.