关于C++ 0x 里垃圾收集器的讲座

原创 2007年07月23日 11:56:00
好像最近C++标准地下工会在公司附近开会,所以我们上班时偶尔可以看到工会成员矫健的身影。我们也近水楼台,得以听到关于C++0x进展的一些科普报告。上次Bjarne Stroustrup做了关于泛型编程的讲座后,Symantec实验室的Michael Spertus也做了一个关于C++ 0x里垃圾收集的讲座。Michael Spertus当年写出了IBM PC上最早的C编译器,也是C++ 0x里垃圾收集器的主要倡议人。
 
Michael从什么是GC开始讲起。三言两语后,谈到在C++ 0x里加入GC的动机。一是许多数据结构,对象,或者资源的生命期难以事先确定、静态管理。我们需要某种形式的动态管理技术。很多老大以为C++高手的标志之一是不需要GC。如果这样想,Unreal的Tim Sweeney就笑了。Unreal引擎里就大量使用GC。如果一个系统需要管理大量对象,要求高吞吐量,但可以容忍偶尔的系统延迟的话,GC是颇为不错的工具。所以3D/建模,2D图像处理等计算都可以用到GC。第二个理由非常有煽动力:帮助C++程序清除内存泄露。我们不必在C++里排斥人肉内存管理。问题是,人肉内存管理难以尽善尽美。大型系统里内存泄露几乎不可避免。每次泄露也不多,10来KB到几个MB。但积累起来,也就造成诸多问题。因为每次泄露量不大,也不像Java等基于GC的语言,“泄露”随时都在发生。所以可以通过定期执行GC来清除这些泄露,也不用消耗过多资源。Michael后来举了一个颇有说服力的例子:某电信公司的交换机,100多万行程序,有持续的内存泄露。每小时必须重启一次。使用GC后,内存泄露消失,交换机不用再定时重启。重启时系统堆上有大概200个线程,500MB内存。这样算来,每线程每小时泄露2.5M。每线程每分钟不过42KB。而每分钟收集42KB内存对系统根本不会有什么影响。最后实测下来,收集500MB不过需要两秒种。分摊到一个小时内,完全可以忽略不计。这样的GC应该叫LC—Litter Collector。还有一个例子是Michael向Mozilla浏览器里注入GC。每次用户操作使得GC回收大概10KB的内存,实在是小菜一碟。
 
Michael接着谈到C++ GC的发展。C++ GC已经成熟,可以标准化了。系统研究的老大们已经做了20年的研究。GC也用到了形形色色的C++系统里。标准化的关键是C++的GC是可选项:GC可以被关掉,而且程序员能够在代码里随时决定用GC还是人肉内存管理。这样才能满足某些系统实时回收资源的要求。而且已有的标准库就不需要重新编译。
 
Michael比较了shared-ptr和GC。GC的主要缺陷是不能即时回收内存,而强项除了方便程序员外,就是性能了。GC的性能(尤其是分摊后的性能)在多方面的基准测试里超过自动指针管理已经不是新闻。Michael举了Boost线程安全基准测试的数据。GC比用share-ptr的测试程序快10倍以上。比Java的hotspot程序或者Gcj编译出的程序快5倍以上。甚至用人肉内存管理的C程序也比GC慢,不过比Boost的程序员快3倍左右。
 
既然GC在C++里用了很多年了,干嘛还要标准化呢?主要有三条原因。一是内置的GC才能读取C++的类型系统。高质量的GC需要知道数据的类型信息。没有类型信息,GC变得非常保守,需要经常扫描大片内存来决定是否能回收某个对象。这样让GC变得很慢。第二个原因是我们需要防止编译优化对GC造成破坏。如果不标准化,标准的C++编译器不可能知道第三方的GC需要什么样的优化。第三是为了允许不同的厂家能共享GC管理的对象。不然微软在某个控件里用了GC,怎么能保证同样的控件到了Borland的系统里也正常回收内存呢?
 
目前的C++ 0x的提议走的是稳健路线。任何功能都要经过实际应用的检验。GC用于特殊场合(比如前面的LC)。通过句法糖的方法实现,也就是说没有新的关键词。API的数目要尽可能小。当然了,C++的类型系统不如Java那么强,所以GC也相应复杂一些。标准提案里包涵了好几种GC类型:
  • gc_required: 所有资源都要通过GC收集。由gc_required控制的区域内所有指针都是经过标注的gc指针。
  • gc_forbidden: 不允许GC。必须人肉回收内存。由gc_forbidden控制的代码区域里只有原始指针。
  • gc_safe:缺省情况。忽略人肉管理的内存,但处理没有被手工回收的部分。
  • gc_strict: GC处理的代码段里整型变量不包含指针(比如不能在DWORD里放指针)。
  • gc_relax: GC处理的代码段里整型变量可以包含指针。这种情况下GC往往需要扫描大量内存来确保安全回收内存。
  • gc_cast: 把一种类型的GC转换成另外一种类型。
 
下面是个例子:
class A {
            A *next;
            B b; // 这里不能用gc_strict, 因为我们不知道B里的数据信息。
            gc_stric int data[10000]; // 我们肯定data数组里没有指针
}
 
同时C++标准库里还提供两个函数:bool std::is_garbage_collected(),和class std::gc_lock()。一个用来检查某块内存是否被GC回收,另外一块用来设定所谓的GC临界区。临界区内的内存不能被回收,这样可以防止GC不合时宜地启动。
 
呵呵,够复杂吧?引入这么多操作的原因之一是要和老的C++系统互动。比如说下面一些情况:
  • 两个DLL,一个用了全局GC,另外一个没有怎么办?如果每个DLL都链接到自己的C类库怎么办?
  • 如果一个共享库希望在内部使用GC,但不影响堆的其它部分怎么办?
  • 如果我们在C++程序内调用libjvm怎么办?libjvm装载后,C++程序可以读取到载入的JVM里的堆,未必我们需要对已经有Java GC控制的内存再做垃圾处理?
 
针对不同的情况,我们得祭出不同的GC。嘿嘿,C++程序员们,准备好你们的钱包哈。如果2009年后C++ 0x开始流行,要买的书就多了。比如Effective C++ GC, Master C++ GC, C++ GC with Legacy Applications,  Modern C++ Design with GC, Expert C++ with GC, Expert C++ without GC。这个世道,不容易啊。
 
 
那finalization嗫?没有了finalization的GC还叫GC么?C++的大仙们当然不会漏掉这么重要的环节。只不过因为finalization本身就很复杂了(比如说回收内存时应该怎样调用回收对象的析构函数?如果回收时立刻调用,会造成线程不安全),所以有另外的提案讨论乐。
 
 

权威黑客知识讲座(一):初识黑客

正文部分     ​    ​ ​黑客,起源于20世纪50年代美国一群高级技术人员。     ​    ​他们坚信编程是一种艺术表达形式,热衷于通过深挖和探测来发掘程序中的漏洞和弱点,然后...
  • baigoocn
  • baigoocn
  • 2015年02月04日 17:20
  • 915

C++0x新特性

我是在一个帖子上摘抄的大神语录。。。感谢supermegaboy大神,给了详尽的解释 下文是一篇转载的Wikipedia的译文,从语言和库两方面概述了C++0x。 右值引用与转移语义 在标准...
  • dongguan131
  • dongguan131
  • 2011年08月20日 00:08
  • 1680

C++最新标准C++ 0x详细介绍

C++是具有国际标准的编程语言,通常称作ANSI/ISO C++,1998年国际标准组织(ISO)颁布了C++语言的国际标准ISO/IEC 1488-1998。。1998年是C++标准委员会成立的第一...
  • ajioy
  • ajioy
  • 2011年09月27日 19:50
  • 4893

垃圾收集器的种类及原理

1、Serial收集器:古老的单线程收集器,作用于新生代。单线程的意义并非仅仅是只使用一条线程进行垃圾回收,更重要的是,在进行垃圾回收的时候,必须暂停其他所有的工作线程,因此,用户体验很不好。单实际上...
  • yanqiaoli
  • yanqiaoli
  • 2017年03月17日 17:09
  • 527

C++ 0X

摘自http://www.wuzesheng.com/?p=1972 参考http://www.ibm.com/developerworks/cn/aix/library/au-gcc/ ...
  • hitrose27
  • hitrose27
  • 2012年07月03日 11:38
  • 1566

"0x%08x"?

"0x%08x" "0x": 普通字符 配合显示16进制格式 "%08x": 8位对齐的16进制格式,少于8位则前补0 如p=1 ==> 0x00000001 p=16 ==>0x0000001...
  • hongboxiang
  • hongboxiang
  • 2014年03月05日 20:53
  • 434

【深入理解JVM】:HotSpot垃圾收集器

相关概念并发和并行这两个名词都是并发编程中的概念,在谈论垃圾收集器的上下文语境中,它们可以解释如下。 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。 并发(Co...
  • u011080472
  • u011080472
  • 2016年05月05日 16:58
  • 2322

就那么几种垃圾收集器

1. Serial收集器     Serial收集器是JAVA虚拟机中最基本、历史最悠久的收集器,在JDK 1.3.1之前是JAVA虚拟机新生代收集的唯一选择。Serial收集器是一个单线程的收...
  • u013782203
  • u013782203
  • 2016年08月16日 16:51
  • 2323

c++11 别名C++0x

C++的最新正式标准,由C++标准委员会于2011年8月12日公布,并于2011年9月出版。2012年2月28日的国际标准草案(N3376)是最接近于现行标准的草案(编辑上的修正)。此次标准为C++9...
  • pizi0475
  • pizi0475
  • 2014年08月30日 08:16
  • 2448

JVM笔记3:Java垃圾收集算法与垃圾收集器

当前商业虚拟机的垃圾收集都采用“分代收集”算法,即根据对象生命周期的不同,将内存划分几块,一般为新生代和老年代,不同的代根据其特点使用不同的垃圾收集算法,主要的垃圾回收算法有:一,标记-清除算法 二,...
  • a19881029
  • a19881029
  • 2013年10月22日 09:37
  • 2898
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于C++ 0x 里垃圾收集器的讲座
举报原因:
原因补充:

(最多只允许输入30个字)