C++对象是怎么死的?进程篇

来源:互联网 发布:第一次sql注入步骤 编辑:程序博客网 时间:2024/04/28 02:59

我承认这个帖子的名称有标题党的嫌疑,但是暂时想不出更好的名称了,只好先这样了 :-( 
  由于前天的帖子聊了架构设计的多进程问题 ,所以今天想起来要聊一下和“C++进程终止”相关的那些事。与前几个C++帖子的风格类似,今天聊的内容,尽量局限于标准C++范畴,尽量不涉及特定的操作系统平台。

  ★关于进程的三种死法 
  由于今天讲的是“进程篇”,自然得先搞明白进程的几种死法。其实进程和大活人一样,也有三种死法,分别是“自然死亡、自杀、它杀”。这三种死亡方式具体如下:
  1、自然死亡
  望文生义,自然死亡就是最自然的进程退出方法。具体表现为通过return语句结束main函数。由于这种方法最优雅(后面会说),如果没有其它特殊原因,强烈建议采用这种死法。
  2、自杀
   所谓的自杀,就是进程自己调用某些API来自行了断。在标准C++中,这几个函数(exit、abort、terminate、unexpected) 可以用于进程自杀。如果没有额外设置,unexpected函数默认会调用terminate函数,terminate函数默认会调用abort函数。所 以自杀的方式基本上也就是exit和abort两种。exit相对abort来说温和一些,所以下文称exit为温和自杀 ;相对地,把abort称为激进自杀 。
  3、它杀
  它杀其实也挺好理解,就是当前进程被其它进程杀死。标准C++没有提供用于它杀的API函数,因此常用的方法是通过某些跨平台的库(如ACE)提供的API函数或者调用某些外部命令(如Posix系统的kill命令)来实现。
  上面说了这几种死法,有同学要问了:进程不同的死法和C++对象有什么关系捏?其实关系大大滴,请听我细细道来。

  ★类对象的析构(销毁) 
  首先把类对象分为三种:局部非静态对象、局部静态对象、非局部对象(出于习惯,以下简称全局对象 )。对于尚不清楚这几种对象差异的同学,请先找本C++入门书拜读一下。进程不同的死法对于这几种对象是否能销毁会有很大的影响。请看如下的对照表:
------------------------------
        局部非静态对象  局部静态对象  全局对象
  自然死亡    能        能      能
  温和自杀    不能       能      能
  激进自杀    不能       不能     不能
   它杀     不能       不能     不能
------------------------------
  从这个对照表可以看出,激进自杀和它杀的效果类似(各种 类对象都无法正常销毁)。所以我们在写程序时要极力避免上述这两种情况。
  另外,温和自杀也有不爽之处:不能正确地销毁局部非静态对象。准确地说,应该是:在调用exit之前已经构造但是尚未析构的局部非静态 对象将再也不会被析构。所以温和自杀也要避免使用。
  综上所述,最正经、最靠谱的死法就是第一种:自然死亡。

  ★析构的顺序 
  那么,是不是只要让进程自然死亡就万事大吉了?非也!即使所有的类对象都会被析构,还有另一个棘手的问题:析构的顺序。先来看下面一个例子:

class CFoo
{
public:
CFoo()
{
cout << "CFoo" << endl;
}
virtual ~CFoo()
{
cout << "~CFoo" << endl;
}
};

  上述示例挺简单的(有效代码仅6行),大伙儿能看出有什么问题吗?如果你一眼就看出问题之所在,恭喜你,后面的内容你不用看了。
   对于用户定义的全局对象,在C++标准中并没有规定它们构造和析构的先后顺序;对于诸如标准输入输出流的cout、cerr等全局对象,在C++ 03标准中(参见27.4.2.1.6章节)有提及如何保证它们在最后析构。但由于某些老式编译器并未完全遵照标准实现,导致标准输入输出流的几个全局对 象也可能 被提前析构。
  基于上述原因,假如CFoo类也定义了一个全局对象g_foo。当g_foo析构的时候,cout对象可能 已经先死了(取决于具体的环境,详见“关于标准输入输出流的进一步探讨 ”)。在这种情况下,CFoo析构函数的打印语句由于引用了已死的对象,可能会 导致不可预料的后果。
  从上面的例子可以看出,如果你在程序中使用了全局对象或者静态对象,那你要非常小心地编写相关class/struct的析构函数代码,尽量不要在它们的析构函数中引用其它的全局对象或静态对象。当然啦,假如能避免使用全局对象和静态对象,就更好了。
  另外,在C++经典名著《Modern C++ Design》的第6章详细描述了关于单键(Singleton)销毁的一些细节、场景及解决方法。大伙儿可以去拜读一下。
  下一个帖子,会聊一下和线程有关的C++对象是怎么死的 。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 餐后血糖高14点怎么办 餐后血糖20多怎么办 空腹血糖6.6饭后9.2怎么办 键盘shift键失效了怎么办 灵异附身夫妻不合怎么办 鞋子买大了半码怎么办 鞋子买小了半码怎么办 黑布鞋鞋面白了怎么办 黑布鞋不黑了怎么办 黑布鞋退白了怎么办 老北京布鞋款式太少怎么办 老人输液抽搐后昏迷怎么办 头七家里有狗怎么办 股票退市股民的钱怎么办 美国股票退市股民怎么办 百度云字幕和视频不同步怎么办 百度云加载字幕有延迟怎么办 很难适应新环境怎么办 蜘蛛丝碰到嘴唇上起包有毒怎么办? 电瓶车在路上爆胎了怎么办 嘴被虫子咬肿了怎么办 高铁管家购票失败怎么办 高铁车厢空调冷怎么办 高铁票过了时间怎么办 网购火车票丢了怎么办 改签没有票了怎么办 火车票取了没赶上车怎么办 上车后车票丢了怎么办 晒了吗任务过期怎么办 坐火车买了站票怎么办 坐火车忘记带票怎么办 距离二本线差几分怎么办 行李包落火车候车厅怎么办 高铁票买错地点怎么办 高铁票买错日期怎么办 票买错时间了怎么办 上高铁了票丢了怎么办 上车前高铁票丢了怎么办 高铁安检没收的东西怎么办 高铁安检员老了怎么办 高铁安检喷雾拍照了怎么办