`
saybody
  • 浏览: 871151 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

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

阅读更多

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

  ★关于进程的三种死法
  由于今天讲的是“进程篇”,自然得先搞明白进程的几种死法。其实进程和大活人一样,也有三种死法,分别是“自然死亡、自杀、它杀”。这三种死亡方式具体如下:
  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++对象是怎么死的


版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者编程随想 和本文原始地址:

http://program-think.blogspot.com/2009/02/cxx-object-destroy-with-process.html

分享到:
评论

相关推荐

    Visual C++实践与提高-COM和COM+篇『PDF』

    2.2 将C++对象移进DLL中——例程DB_cppdll 2.2.1 成员函数的引出 2.2.2 内存分配 2.2.3 Unicode/ASCII兼容 2.2.4 例程实现 2.2.4.1 修改接口文件 2.2.4.2 修改对象程序 2.2.4.3 修改客户程序 2.3 C++对象使用...

    21天学通Visual C++ 光盘part2

    第四篇主要讲解Visual C++的开发,包括数据库编程、网络编程、线程同步与进程通信、动态链接库、ActiveX技术和Visual C++的调试技术。第五篇案例篇讲解了如何应用Visual C++进行实际综合案例开发。 本书重点分析了...

    21天学通Visual C++ 光盘part3

    第四篇主要讲解Visual C++的开发,包括数据库编程、网络编程、线程同步与进程通信、动态链接库、ActiveX技术和Visual C++的调试技术。第五篇案例篇讲解了如何应用Visual C++进行实际综合案例开发。 本书重点分析了...

    21天学通Visual C++ ppt

    第四篇主要讲解Visual C++的开发,包括数据库编程、网络编程、线程同步与进程通信、动态链接库、ActiveX技术和Visual C++的调试技术。第五篇案例篇讲解了如何应用Visual C++进行实际综合案例开发。

    21天学通Visual C++.part3

    第四篇主要讲解Visual C++的开发,包括数据库编程、网络编程、线程同步与进程通信、动态链接库、ActiveX技术和Visual C++的调试技术。第五篇案例篇讲解了如何应用Visual C++进行实际综合案例开发。

    21天学通Visual C++ 光盘part1

    第四篇主要讲解Visual C++的开发,包括数据库编程、网络编程、线程同步与进程通信、动态链接库、ActiveX技术和Visual C++的调试技术。第五篇案例篇讲解了如何应用Visual C++进行实际综合案例开发。 本书重点分析了...

    visual C++从初学到精通源代码

    第一篇 Visual C++基础 第1章 Visual C++集成开发环境 第2章 使用Visual C++创建基本应用程序 第3章 面向对象程序设计基础 第4章 Visual C++调试技术 第二篇 Windows编程 第5章 Windows程序设计 第6章 MFC编程概述 ...

    C++教程网《Linux网络编程》视频百度云地址

    Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输...

    C++标准库介绍.pdf

    标准c库大全:C++标准库介绍 疯狂代码 http://CrazyCoder.cn/ ĵ:http:/CrazyCoder.cn/VC/Article12860.html  标准库中提供了C基本设施虽然C标准库随着C标准折腾了许多年直到标准出台才正式定型但是在标准库实 现上...

    2018年C++教程网的linux网络编程视频共41集百度云下载链接.rar

    Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输单元...

    [免费]2018年C++教程网的linux网络编程视频百度云下载链接.rar

    Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输...

    Visual C++实践与提高——串口通信与工程应用篇1

    4.4.2 使用互斥对象(Mutex) 83 4.4.3 使用信号量(Semaphore) 84 4.4.4 使用事件(Event) 84 4.4.5 各种方法的比较 85 4.5 多线程串口程序设计 85 4.5.1 多线程的应用框架 85 4.5.2 相关的声明 86 4.5.3 创建...

    77G 22套C语言 C++ 数据结构 程序设计视频课程合集 C丨C++相关学习视频全套视频教程

    VC++ MFC 经典教程 - 基础篇 1.CP_YourFirstWindowsProgram.mp4 10.MFC_GDI_画直线和曲线.mp4 11.MFC_GDI_画椭圆_多边形及其他形状.mp4 12.MFC_GDI_画笔和画刷.mp4 13.MFC_GDI_画文本和字体.mp4 14.MFC_GDI_...

    c++教程网的linux网络编程视频下载

    Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输...

    C++教程网视频:linux网络编程

    Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输...

    1上篇:ACE技术论文集

    ACE自适配通信环境(Adaptive Communication Environment)是一种面向对象(OO)的工具包,它实现了通信软件的许多基本的设计模式。ACE的目标用户是在UNIX和Win32平台上开发高性能通信服务和应用的开发者。ACE简化了...

    《Android系统源代码情景分析》

    第1篇 初识Android系统 第1章 准备知识 1.1 Linux内核参考书籍 1.2 Android应用程序参考书籍 1.3 下载、编译和运行Android源代码 1.3.1 下载Android源代码 1.3.2 编译Android源代码 1.3.3 运行Android...

Global site tag (gtag.js) - Google Analytics