1、mian函数中抛异常
/************* 异常的最终处理 **************/
#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;
}
2、异常的最终处理
2.1、如果main中异常无法被处理,terminate()结束函数会被自动调用
2.2、默认情况下,terminate()调用abort()库函数来终止程序
2.3、
abort()函数使得程序执行异常而立即退出。而不会像exit会先进行一些清理工作(如调用全局对象或静态局部对象的析构函数),再退出进程。
2.4、
C++支持替换默认的terminate()函数实现。
3、自定义结束函数 (terminate)
3.1、
自定义一个无返回值无参数的函数
3.1.1、
不能抛出任何异常
3.1.2、 函数中必须以某种方式结束当前程序(如exit或abort)
3.2、
调用set_terminate()设置自定义的结束函数
3.2.1、
参数类型为void(*)()
3.2.2、
返回值为默认的terminate()函数的入口地址
/********** 自定义结束函数 ************/
#include <iostream>
#include <cstdlib>
using namespace std;
//自定义结束函数
void my_terminate()
{
cout << "void my_terminate()" << endl;
//abort();//并不会清理全局变量
exit(1);//调用exit会进行一些清理工作(如调用全局对象或静态局部对象的析构函数来进行清理),,只会清理一些全局变量
}
class Test
{
public:
Test()
{
cout << "Test() " << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
int main()
{
set_terminate(my_terminate); //抛出异常没处理的话,系统自动调用这个函数,参数是无参函数指针,这是自定义的结束函数
static Test t;//如果是局部变量,异常发生时析构函数不会被调用,因为,当异常发生后,会先执行my_terminate()结束,而该函数内调用的exit函数会清理全局变量。静态局部变量。
throw 1;
return 0;
}
4、析构函数中抛异常会发生什么(面试题)
4.1、
可能造成terminate函数被重复调用
4.2、
由terminate的重复调用,可能造成资源重复释放,从而造成系统的不稳定。
4.3、 导致资源得不到正确的释放 。
/******** 析构函数中抛异常 ********/
#include <iostream>
#include <cstdlib>
#include <exception>
using namespace std;
void my_terminate()
{
cout << "void my_terminate()" << endl;
exit(1); //会进行一些全局函数的清理工作。。exit函数会清理全局变量。静态局部变量。
//abort(); //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;//1。 由于main函数没有处理这个异常,会被传递到my_terminate中处理,这里是第一次调用my_terminate函数。
//2。又因为my_terminate中调用了exit函数,会去清理全局变量,如调用t的构造函数来清理。但是构造函数中也抛出了一个异常,这将导致my_terminate函数重复被调用,造成资源的重复释放,从而造成系统的不稳定,(linux中做了处理,别的系统中就不一定做处理了。)
return 0;
}
5、小结
5.1、
如果异常没有被处理,最后terminate()结束整个程序
5.2、
terminate()是整个程序释放系统资源的最后机会
5.3、
结束函数可以自定义(可以set),但不能继续抛出异常
5.4、
析构函数中不能抛出异常,可能导致terminate()多次调用