main 函数中抛出异常
问题: 如果在main函数中抛出异常会发生什么?
- 如果异常不处理,最后会传到哪里?
编程实验: 异常的最终处理
下面的代码会输出什么呢?
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
int main()
{
static Test t;
throw 1;
return 0;
}
输出:【g++】
Test()
terminate called after throwing an instance of 'int'
已放弃
输出:【vc++2010】
Test()
...
应用程序自动退出...
思考:
不同的编译器为什么有不同的行为,g++ 中的提示信息是在哪里打印的呢?
- 如果异常无法被处理, terminate() 结束函数会被自动调用
- 默认情况下, terminate() 调用库函数 abort() 终止程序
- abort() 函数使得程序执行异常而立即退出
- C++ 支持替换默认的 terminate() 函数实现
terminate() 函数的替换
自定义一个无返回值无参数的函数
- 不能抛出任何异常
- 必须以某种方式结束当前程序
调用 set_terminate() 设置自定义的结束函数
- 参数类型为 void(*)()
- 返回值为默认的 terminate() 函数入口地址
编程实验: 自定义结束函数
#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()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
int main()
{
set_terminate(my_terminate);
static Test t;
throw 1;
return 0;
}
输出:[g++]
Test()
void my_terminate()
~Test()
输出:[vc++2010]
Test()
void my_terminate()
~Test()
分析: 析构函数为什么会被调用呢?
- abort() : 使应用程序异常停止,立即退出
- exit(x) : 确保所有的全局对象和静态局部对象正常析构后,程序退出
当 my_terminate() 为 abort() 时:
输出:[g++]
Test()
void my_terminate()
已放弃
输出:[vc++2010]
Test()
void my_terminate()
...
应用程序自动退出...
析构函数中抛出异常
面试题: 如果析构函数中抛出异常会发生什么情况呢?
编程实验: 析构函数抛出异常
#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()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
throw 2;
}
};
int main()
{
set_terminate(my_terminate);
static Test t;
throw 1;
return 0;
}
输出:
Test()
void my_terminate()
~Test()
void my_terminate()
分析:
第一次 "void my_terminate()" : main() 函数中抛出的异常
第二次 "void my_terminate()" : exit(1) 促使所有全局对象与静态局部对象销毁,析构函数被调用,抛出异常
- 析构函数用来释放资源,如果在析构函数中抛出异常,资源可能得不到正确释放。
- 有可能导致全局的 terminate 函数被重读调用,重复调用是未定义行为,甚至可能影响系统安全。
my_terminate 进行应用程序级别的资源释放。而重复释放的行为是未定义,因此默认的 terminate 函数中使用 abort() 异常退出程序来避免构造函数被执行(防止析构函数中再次抛出异常)
设计原则 : 不允许在析构函数中抛出异常
小结
- 如果异常没有被处理,最后 terminate() 结束整个程序
- terminagte() 是整个程序释放资源的最后机会
- 结束函数可以自定义,但不能继续抛出异常
- 析构函数中不能抛出异常,可能导致 terminate() 多次调用
以上内容参考狄泰软件学院系列课程,请大家保护原创!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。