问题:如果在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;
}
不同的编译器打印结果是不同的,但是根据我们编写的程序,不管哪款编译器Test()是肯定会被打印的。差异就在下面打印的东西。使用的该款编译器,当抛出异常时terminate函数被调用了。
如果异常无法被处理,terminate()结束函数会被自动调用默认情况下,terminate()调用库函数abort()终止程序abort()函数使得程序执行异常而立即退出C++支持替换默认的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;
}
exit函数会确保所有的全局对象和静态局部对象全部被正常的析构。如果不调用exit,而是调用abort,又会发生什么?
不会调用析构函数,abort是异常终止一个程序,当它异常终止一个程序时,不会调用任何对象的析构函数。
通过本实验,可以得出下面两条结论:
1.在main函数中所扔出的异常如果没有被处理,最终将被一个全局函数处理掉。2.c++编译器之间存在差异
如果析构函数中抛出异常会发生什么情况?
#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;
}
你会发现全局函数my_terminate被重复的调用。
已经调用了析构函数,又重复调用析构函数。类似于一个指针指向了堆空间中的一片内存,delete一次就把它释放掉了,如果delete两次就会有问题,造成整个应用程序的不稳定。
当把exit函数换成abort时,又会怎样呢?前面已经说过abort函数是不会调用析构函数的
从而就解释了,在terminate函数中,C++默认调用的是abort,而不是exit了。因为abort函数强制的结束当前的应用程序了,它不会去调用析构函数,就是害怕析构函数中又抛出异常
现在可以回答上面提出的问题了,可以在析构函数中扔出异常,但一定不要这样做。这样做会导致很多问题。
原则:在析构函数中一定不要抛出异常,原因如下:
析构函数是用来释放资源的地方,如果抛出异常,有可能导致资源得不到正确的释放在析构函数里面抛出异常有可能导致全局的结束函数terminate被重复的调用,这是极其可怕的事情,有可能让系统进入极其不稳定的状态。
小结:
![](https://i-blog.csdnimg.cn/blog_migrate/4c93d1cb85a67e6fdc2880d4f05eeeaa.png)
terminate函数 可以在调用abort函数之前,打印一些字符串,弹出一个对话框出来。