1、问题
如果在 main
函数中抛出异常会发生什么?
- 如果异常不处理,最后会传到哪里?
- 下面的代码输出什么?
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test():"<< endl;
}
~Test()
{
cout << "~Test():" << endl;
}
};
int main()
{
static Test t;
throw 1;
return 0;
}
翻译一下就是:terminate
在 抛出异常之后被调用
2、解析
- 如果异常无法被处理,
terminate()
结束函数会被自动调用 - 默认情况下,
terminate()
调用库函数abort()
终止程序 abort()
函数使得程序执行异常而立即退出- C++支持替换默认的
terminate()
函数实现
3、terminate() 函数的替换
— 自定义一个无返回值无参数的函数(头文件:#include <cstdlib>
)
1、不能抛出异常
2、必须以某种方式结束当前程序
— 调用 set_terminate()设置自定义的结束函数
1、参数类型为 void (*)()
2、返回值为默认的 terminate()
函数入口地址
程序:自定义结束函数
#include <iostream>
#include <cstdlib>
#include <exception>
using namespace std;
void my_terminate()
{
cout << "void my_terminate()" << endl;
//abort(); //异常终止不会调用任何函数的析构函数
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;
}
3、面试题
- 面试题
如果析构函数中抛出异常会发生什么情况?
#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():"<< endl;
}
~Test()
{
cout << "~Test():" << endl;
throw 2;
}
};
int main()
{
set_terminate(my_terminate);
static Test t;
throw 1;
return 0;
}
流程:先构造函数—产生异常—调用自定义 terminate 函数,由exit(1)
确保所有的全局对象和静态局部对象析构完毕–调用析构函数–产生异常–调用自定义 terminate 函数
这里就有问题了,我们调用了两次自定义 terminate 函数,我们都说 terminate 函数是函数最后的终止程序,为什么会终止两次呢,所以我们不能在析构函数中抛出异常。所以C++库中的 terminate 函数都是调用 abort 函数,强制结束当前程序,防止析构函数中再抛出异常。
小结:
- 如果异常没有被处理,最后
terminate()
结束整个程序 terminate()
是整个程序释放系统资源的最后机会- 结束函数可以自定义,但不能继续抛出异常
- 析构函数中不能抛出异常,可能导致
terminate()
多次调用