GC垃圾回收 与 C++引用计数算法
GC(垃圾收集garbage collection)
垃圾收集器是一种动态存储分配器,它自动释放程序不再需要的已分配的块,这些块也称为垃圾。在程序员看来,垃圾就是不再被引用的对象。自动回收垃圾的过程则称为垃圾收集(garbage collection)。在一个支持垃圾收集的语言中,程序显式地申请内存,但从不需要显式的释放它们。垃圾收集器会定期识别垃圾块,并将垃圾块放回空闲链表中。显然,C语言的malloc包不是一个带GC功能的分配器,程序员显式 调用malloc分配内存,也需要显式调用free释放它。而像java、C#这些语言等则提供了垃圾收集器。
有向可达图与根集
垃圾收集器将存储器视为一张有向可达图。图中的节点可以分为两组:一组称为根节点,对应于不在堆中的位置,这些位置可以是寄存器、栈中的变量,或者是虚拟存储器中读写数据区域的全局变量;另外一组称为堆节点,对应于堆中一个分配块,如下图:
当存在一个根节点可到达某个堆节点时,我们称该堆节点是可达的,反之称为不可达。不可达堆节点为垃圾。可见垃圾收集的目标即是从从根集出发,寻找未被引用的堆节点,并将其释放。
引用计数算法
引用计数算法是唯一一种不用用到根集概念的GC算法。其基本思路是为每个对象加一个计数器,计数器记录的是所有指向该对象的引用数量。每次有一个新的引用指向这个对象时,计数器加一;反之,如果指向该对象的引用被置空或指向其它对象,则计数器减一。当计数器的值为0时,则自动删除这个对象。这个思路可以参考C++ 引用计数技术及智能指针的简单实现。
引用计数算法的优点是实现简单,在原生不支持GC的语言中也能容易实现出来。另一个优点这种垃圾收集机制是即时回收,也即是对象不再被引用的瞬间就立即被释放掉。而其缺点是若存在对象的循环引用,无法释放这些对象,例图:
缺点二是多个线程同时对引用计数进行增减时,引用计数的值可能会产生不一致的问题,必须使用并发控制机制解决这一问题,也是一个不小的开销。
2、 Mark & Sweep 算法(标记清除算法)
3、 节点复制算法
C++垃圾回收机制
C语言本身没有提供GC机制,而C++ 11则提供了基于引用计数算法的智能指针进行内存管理。也有一些不作为C++标准的垃圾回收库,如著名的Boehm库。借助其他的算法也可以实现C/C++的GC机制,如前面所说的标记清除算法。