如何在C++中实现垃圾收集

Jos*_*son 47 c++ garbage-collection

我在C中看到了一些关于实现GC的帖子,有些人说这是不可能的,因为C是弱类型的.我想知道如何在C++中实现GC.

我想要了解如何做到这一点.非常感谢你!

这是我朋友告诉我的彭博采访问题.那时他做得很糟糕.我们想知道您对此的看法.

tem*_*def 55

C和C++中的垃圾收集都是困难的主题,原因如下:

  1. 指针可以对整数进行类型转换,反之亦然.这意味着我可以拥有一块只能通过获取整数来访问的内存块,将其类型化为指针,然后取消引用它.垃圾收集器必须小心,不要认为块确实无法到达时仍然可以到达.

  2. 指针不是不透明的.许多垃圾收集器,如停止和复制收集器,喜欢移动内存块或压缩它们以节省空间.由于您可以在C和C++中显式查看指针值,因此很难正确实现.你必须确定,如果有人通过对整数进行类型转换来做一些棘手的操作,那么如果你移动了一块内存,你就可以正确地更新整数.

  3. 内存管理可以明确地完成.任何垃圾收集器都需要考虑用户能够随时显式释放内存块.

  4. 在C++中,分配/释放与对象构造/销毁之间存在分离.可以分配具有足够空间的存储器块来保持对象,而不在那里实际构造任何对象.一个好的垃圾收集器在收回内存时需要知道是否为可能在那里分配的任何对象调用析构函数.对于标准库容器尤其如此,std::allocator出于效率原因,这些容器通常利用此技巧.

  5. 可以从不同区域分配内存.C和C++可以从内置的freestore(malloc/free或new/delete)获取内存,也可以从OS mmap或其他系统调用中获取内存,对于C++,可以从get_temporary_bufferreturn_temporary_buffer.程序也可能从某些第三方库中获取内存.一个好的垃圾收集器需要能够跟踪这些其他池中对内存的引用,并且(可能)必须负责清理它们.

  6. 指针可以指向对象或数组的中间.在许多垃圾收集语言(如Java)中,对象引用始终指向对象的开头.在C和C++中,指针可以指向数组的中间,而在C++中指向对象的中间(如果使用多重继承).这可能会极大地复杂化检测仍然可以访问的逻辑.

因此,简而言之,为C或C++构建垃圾收集器非常困难.大多数在C和C++中进行垃圾收集的库在它们的方法中非常保守并且技术上不健全 - 例如,他们假设您不会使用指针,将其转换为整数,将其写入磁盘,然后加载它稍晚回来了.他们还假设内存中任何指针大小的值都可能是指针,因此有时会拒绝释放无法访问的内存,因为有一个非零的机会指向它.

正如其他人所指出的那样,Boehm GC确实为C和C++做了垃圾收集,但受到上述限制.

有趣的是,C++ 11包含一些新的库函数,允许程序员将内存区域标记为可达且无法访问,以预期将来的垃圾收集工作.将来有可能用这种信息构建一个非常好的C++ 11垃圾收集器.在此期间,您需要非常小心,不要破坏上述任何规则.

  • "这意味着我可以拥有一块只能通过获取整数,将其类型转换为指针,然后取消引用它的内存块." - 并且没有GC算法可以应对`intptr_t x = rand(); intptr_t y =((intptr_t)p)^ x;/*丢弃p然后一段时间后*/; use_the_ptr((字符*)(X ^ Y));`.您需要来自用户的一些合作. (2认同)
  • C++ 11中的哪些新库函数允许这样做?我很想知道:) (2认同)