C ++中的垃圾收集库


69

哪些免费的和商业的垃圾收集库可用于C ++,每种都有哪些优缺点?

我对在该领域的实际使用中来之不易的教训感兴趣,而不是市场营销或促销宣传中的教训。

无需详细说明与自动垃圾收集相关的通常的取舍,但是请务必提及所使用的算法(引用计数,标记和清除,增量等),并简要总结其后果。


9
重新开放的原因:在原始发布时,SO上尚未禁止软件建议。追溯地应用规则是邪恶的行为,尤其是因为还存在将问题标记为历史问题的可能性,这就是我建议的做法。因此,我标记了要重新打开的问题。
peterh-恢复莫妮卡

managedcpp.sourceforge.net使用BoehmGC但对于C ++特别是使用C ++ 11。
Zach Saw

Answers:


30

过去,我使用Boehm收集器取得了成功。它是开源的,可以在商业软件中使用。

它是一个保守的收集器,并且由垃圾收集技术领域最重要的研究人员之一开发了很长的历史。


一点说明:Boehm GC不遵循指针和分配的内存区域。它甚至不知道内存地址是否是指针。因此,使用Boehm GC的1)仍然存在未使用的存储区域无法再释放的可能性(如果它们由不是指针的数据“引用”)。2)boehm GC还会扫描非指针数据中的“ pointers”,如果指针少但数据很多(例如,您有很多大数据块),则意味着大量开销3)Boehm GC是纯C语言,几乎不使用C预处理程序4)它不是线程安全的。
彼得-恢复莫妮卡

23

Boost的范围很广 智能指针,这些指针可以隐含引用计数或范围内删除或侵入式引用计数。这些已经证明足以满足我们的需求。最大的优点是,它都是免费的,开源的,模板化的C ++。因为它是引用计数,所以在大多数情况下,销毁对象时具有高度确定性。


我使用auto_ptr取得了很大的成功。
Kieveli 2009年

8
加克 应将Auto_ptr拖出谷仓后面并射击。它有它的用途,但有孩子:切勿将auto_ptr和集合混合使用。坏枣结果。
克里斯K,2009年

1
@darthcoder -同意,但任何C ++实现,允许你混合的auto_ptr和收藏也应拖出谷仓等落后
丹尼尔·埃里克

9
@Tom Leys-应该记住,引用计数的智能指针不是GC的实现。它们不会自动处理循环引用,并且在实际应用中它们的性能会较差(很多不必要的簿记工作,所有这些工作都是在负载最大的时间而不是在空闲时间执行的)。
Daniel Earwicker,2009年

5
我还要质疑shared_ptr有用的“确定性”想法。本地对象实例上的析构函数可确定地运行-我们知道它在退出封闭块时执行。但是在与相同的情况下shared_ptr,我们所知道的是refcount已减少。整个问题的关键shared_ptr是我们不知道该对象是否在其他地方仍然需要,因此我们无法在本地确定该对象何时被销毁。如果您需要在退出某个范围之前关闭“文件句柄”对象,请不要使用shared_ptr
Daniel Earwicker,2009年

10

我经常使用boehm-gc。使用起来很简单,但是文档确实很差。有一个C ++页面,但是很难找到。

基本上,您只需确保每个类都从其基类继承,并且始终将gc_allocator传递给容器。在许多情况下,您想使用libgccpp来捕获new和delete的其他用途。这些主要是高层更改,我们发现可以在编译时使用#ifdef关闭GC,支持该更改仅会影响一个或两个文件。

我的主要问题是,除非您先关闭收集器,否则您将无法再使用Valgrind。关闭收集器很容易做到,并且不需要重新编译,但是,如果开始耗尽内存,显然不可能使用它。


Afaik Boehm GC在某些项目中可能有用,但是它具有严重的后备功能,尤其是对于接近Java的任务。例如,它不是线程安全的,或者将数据视为指针。详细列表在这里
peterh-恢复莫妮卡

BoehmGC的C ++部分非常不完整。有关如何使用它在C ++ 11中具有实际精确GC的示例,请参见managedcpp.sourceforge.net
Zach Saw

9

Boehm垃圾收集器是免费提供的,并且据说还不错(没有亲身经历)

([PDF警告]关于Boehm垃圾收集器的C ++ 0x建议的理论论文)

最初据说是C ++ 0x ,但毕竟不会(由于我认为时间限制)。

Proprosal N2670(对垃圾收集器的最小支持)确实在2008年6月获得批准,因此随着编译器实现的发展,以及标准的最终确定,C ++的垃圾收集世界肯定会发生变化...


Afaik的建议N2670是插入Boehm GC的不错选择,此处详细介绍其严重的后备问题
peterh-恢复莫妮卡

2

我所知道的唯一一个是Boehm,它的底部是传统的标记和横扫。它可能使用各种技术来对此进行优化,但是通常如果不使用托管子集(如.Net C ++所能提供的),就很难为C ++创建增量/世代/压缩GC。某些需要移动指针的方法可以通过编译器支持固定指针或读/写块的方式来实现,但对性能的影响可能太大,并且不一定对GC进行重大更改。


好吧,没有GC需要解释程序...也许您的意思是它需要编译器支持。
dev1223 '16

Afaik Boehm GC在某些项目中可能有用,但是它具有严重的后备功能,尤其是对于接近Java的任务。例如,它不是线程安全的,或者将数据视为指针。详细列表在这里
peterh-恢复莫妮卡

2

从GC的角度来看,C ++中GC的主要困难是需要处理不合作的模块。即,处理从未考虑过G​​C的库。

这就是为什么经常建议使用Boehm GC的原因。


幸运的是,对于已编译的Java代码,使用非gc库的可能性要小得多。
peterh-恢复莫妮卡


1

您也可以使用Microsoft的Managed C ++。CLR和GC非常牢固,并用于服务器产品中,但是必须使用CLR类型才能使GC实际收集-您不能只重新编译现有代码并删除所有delete语句。

我宁愿使用C#编写全新的代码,但是Managed C ++允许您以更渐进的方式发展代码库。


3
缺点:1)它是Microsoft特定的2)它将代码编译为CLR,即用于VM。
peterh-恢复莫妮卡

1

阅读此内容并仔细查看结论:

结论

  • 解决问题的复杂解决方案已被广泛使用,并且可以通过C ++ 0x加以改进,因此我们几乎不需要。

  • 我们对建议的标准语言功能几乎没有经验。

  • 修复不良的软件复杂系统将永远无法进行。

  • 建议对次要语言进行更改以改善将来对GC的支持-例如,不允许隐藏指针(“异或列表技巧”)。

  • 最后-正视“ C ++不好,因为它没有GC”这一说法。C ++不会产生垃圾,因此不需要GC。显然,Java,C#,Objective C等会产生大量垃圾。

是的,最后一句话是主观的,也是圣战的一部分。
我使用C ++是因为我不喜欢有人需要为我清除垃圾的想法。
市政厅做到了,对我来说就足够了。
如果需要GC,请使用其他语言。为正确的工作选择正确的工具。


13
您的结论是完全从头至尾的。在C ++程序中,必须手动设计垃圾的收集方式。(可能是您,可能是下一个必须修复内存泄漏的可怜人)。在具有集成GC的语言中,没有人需要这样做。已经知道了。如果要减少人员要做的毫无意义的工作,请基于GC进行工作。
Daniel Earwicker,2009年

^丹尼尔说。另外,hpl.hp.com / personal / Hans_Boehm /gc/ issues.html是关于GC优缺点的很好的讨论,而不是显式的内存管理。
制造商史蒂夫

在需要GC的c ++中,通常可以找到更合适,性能更高的解决方案。典型的用例是场景图。场景图需要压缩以清除内存中的漏洞。Gc可以做到这一点,但是在C ++中,您不需要清除垃圾(额外且昂贵的任务)。您只需要快速使用空的内存缓冲区即可。
CoffeDeveloper

事实并非如此,C ++会因为您的数据结构至少在即席图的复杂性上产生垃圾。对于GC,您需要使用临时解决方案,是的,尽管开发人员的临时gc付出了巨大的努力,但日常经验是大型C ++二进制文件确实会泄漏。(嗯,java进程也会泄漏,但是在java中,gc所需的工作时间几乎总是在零附近)。
peterh-恢复莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.