0、先修知识
1、问题
如果在main函数中抛出异常会发生什么?
如果异常不处理,最后会传到哪里?
下面的代码输出什么?
2、编程实验
异常的最终处理 E1-1.cpp
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test()";
cout << endl;
}
~Test()
{
cout << "~Test()";
cout << endl;
}
};
int main()
{
static Test t;
throw 1;
return 0;
}
BCC101
VS2015
VS2010会弹出一个窗口
g++
3、异常处理深度解析
如果异常无法被处理,terminate()结束函数会被自动调用
默认情况下,terminate()调用库函数abort()终止程序
abort()函数使得程序执行异常而立即退出
C++支持替换默认的terminate()函数实现
terminate()函数的替换
-自定义一个无返回值无参数的函数
不能抛出任何异常
必须以某种方式结束当前程序
- 调用set_ terminate()设置自定义的结束函数
参数类型为void (*) ()
返回值为默认的terminate()函数入口地址
4、编程实验
自定义结束函数 El-2.cpp
#include <iostream>
#include <cstdlib>
#include <exception>
using namespace std;
void my_terminate()
{
cout << "void my_terminate()" << endl;
exit(1);
}
class Test
{
public:
Test()
{
cout << "Test()";
cout << endl;
}
~Test()
{
cout << "~Test()";
cout << endl;
}
};
int main()
{
set_terminate(my_terminate);
static Test t;
throw 1;
return 0;
}
exit():
在调用时,会做大部分清理工作,但是决不会销毁局部对象,因为没有stack unwinding。会进行的清理工作包括:销毁所有static和global对象,清空所有缓冲区,关闭所有I/O 通道。
终止前会调用经由atexit()登录的函数,atexit如果抛出异常,则调用terminate():
abort():
调用时,不进行任何清理工作。直接终止程序。
retrun:
调用时,进行stack unwinding,调用局部对象析构函数,清理局部对象。如果在main中,则之后再交由系统调用exit()。
6、面试题
如果析构函数中抛出异常会发生什么情况?
7、编程实验
析构函数抛出异常 E1-3.cpp
#include <iostream>
#include <cstdlib>
#include <exception>
using namespace std;
void my_terminate()
{
cout << "void my_terminate()" << endl;
exit(1);
// abort();
}
class Test
{
public:
Test()
{
cout << "Test()";
cout << endl;
}
~Test()
{
cout << "~Test()";
cout << endl;
throw 2;
}
};
int main()
{
set_terminate(my_terminate);
static Test t;
throw 1;
return 0;
}
不安全,所以推荐使用abort(),这也是标准库中使用abort()的原因
8、小结
如果异常没有被处理,最后terminate()结束整个程序
terminate()是整个程序释放系统资源的最后机会
结束函数可以自定义,但不能继续抛出异常
析构函数中不能抛出异常,可能导致terminate()多次调用