【问题标题】:Regarding mark-sweep ( lazy approach ) for garbage collection in C++?关于 C++ 中垃圾收集的标记扫描(惰性方法)?
【发布时间】:2011-07-08 13:57:24
【问题描述】:

我知道引用计数器技术,但直到今天在阅读名为“编程语言概念”的书时才听说过标记扫描技术。
根据书:

垃圾回收的原始标记-清除过程操作如下:运行时系统根据请求分配存储单元,并根据需要断开与单元的指针,而不考虑存储回收(允许垃圾积累),直到它分配了所有可用的细胞。此时,开始进行标记清除过程,以收集在堆中漂浮的所有垃圾。为了简化这个过程,每个堆单元都有一个额外的指示位或字段,供收集算法使用。

根据我有限的理解,C++ 库中的智能指针使用引用计数技术。我想知道 C++ 中是否有任何库使用这种智能指针实现?由于这本书纯粹是理论性的,我无法想象实现是如何完成的。一个证明这个想法的例子将非常有价值。如果我错了,请纠正我。

谢谢,

【问题讨论】:

    标签: c++ garbage-collection mark-and-sweep


    【解决方案1】:

    在 C++ 中使用垃圾回收有一个难点,就是要识别什么是指针,什么不是。

    如果您可以调整编译器以为每种对象类型提供此信息,那么您就完成了,但如果您不能,那么您需要使用保守的方法:即扫描内存以搜索可能存在的任何模式看起来像一个指针。这里还有“位填充”的难点,人们将位填充到指针中(高位在 64 位中大多未使用)或异或两个不同的指针以“节省空间”。

    现在,标准委员会在 C++0x 中引入了标准 ABI 来帮助实现垃圾收集。在 n3225 中,您可以在 20.9.11 Pointer safety [util.dynamic.safety] 找到它。当然,这假设人们将为他们的类型实现这些功能:

    void declare_reachable(void* p); // throw std::bad_alloc
    template <typename T> T* undeclare_reachable(T* p) noexcept;
    
    void declare_no_pointers(char* p, size_t n) noexcept;
    void undeclare_no_pointers(char* p, size_t n) noexcept;
    
    pointer_safety get_pointer_safety() noexcept;
    

    实施后,它将授权您将任何垃圾收集方案(定义这些功能)插入您的应用程序。当然,在需要的地方实际提供这些操作当然需要一些工作。一种解决方案可能是简单地覆盖newdelete,但它不考虑指针运算...

    最后,垃圾收集有很多策略:引用计数(使用循环检测算法)和标记和扫描是主要的不同系统,但它们有不同的风格(是否生成,是否复制/压缩,.. .).

    【讨论】:

      【解决方案2】:

      尽管他们现在可能已经对其进行了升级,但 Mozilla Firefox 曾经使用一种混合方法,其中尽可能使用引用计数的智能指针,并使用并行运行的标记和清除垃圾收集器来清理引用周期。其他项目可能已经采用了这种方法,尽管我不确定。

      我可以看到 C++ 程序员避免这种类型的垃圾收集的主要原因是它意味着对象析构函数将异步运行。这意味着,如果创建了保留重要资源(例如网络连接或物理硬件)的任何对象,则无法保证及时进行清理。此外,如果要访问共享资源,析构函数必须非常小心地使用适当的同步,而在单线程、直接引用计数解决方案中,这不是必需的。

      这种方法的另一个复杂性是 C++ 允许对指针进行原始算术运算,这使任何垃圾收集器的实现变得非常复杂。可以保守地解决这个问题(例如,看看 Boehm GC),尽管它是构建此类系统的一个重大障碍。

      【讨论】:

      • Python C 实现也使用 refcounted 指针 + 垃圾回收来进行垃圾循环。
      • 有可能设计一个 GC 来处理那些不会对垃圾收集器产生恶意的程序,但可以使用任何可以将指针转换为的语言一系列字节和任意一系列字节都可以变成一个指针,解决垃圾收集问题就相当于解决了停机问题。实际上,对于交互式程序,情况会更糟,因为包含指针的字节可以存储在计算机之外的某个地方。程序无法知道指针是否可以重构。
      猜你喜欢
      • 1970-01-01
      • 2018-10-30
      • 1970-01-01
      • 2014-12-04
      • 2019-10-06
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 2010-09-10
      相关资源
      最近更新 更多