我想知道如何使用C ++全功能指针算法实现垃圾收集器。此外,在像Java这样的语言中,我无法为引用分配文字地址。在C ++中,它非常灵活。
我相信C#都有,但C#中的不安全指针又是程序员的责任。
EITD ::伙计们,我问C ++指针'他们目前'是否可以在理论上进行GC操作?
答案 0 :(得分:9)
指针算术不是根本问题。 GC必须处理指针一直被重新分配,指针算术只是另一个例子。 (当然,如果允许指向不同缓冲区的指针之间的指针运算,它会导致问题,但事实并非如此。你可以在指向数组A的指针上执行的唯一算术是重新定位它的那些算法。在那个阵列中。
真正的问题是缺少元数据。 GC必须知道什么是指针,什么不是。
如果遇到值0x27a2c230
,则必须能够确定它是否为
它还必须能够确定结构的范围。假设值是一个指针,它指向另一个结构,GC必须能够确定该结构的大小和范围,因此它知道应该扫描哪个地址范围以获得更多指针
GC的语言有很多基础设施可以解决这个问题。 C ++没有。
Boehm的GC是你通常可以得到的最接近的GC,它是保守的,如果可能是一个指针,GC认为它是一个,这意味着一些数据不必要地保持活着。因此,它可能会保持数据存活,这应该是GC。
或者,当然所有这些基础设施 原则上都可以添加到C ++编译器中。标准中没有规则允许它不存在。问题在于它将成为主要的性能影响并消除许多优化机会。
答案 1 :(得分:3)
是。 20世纪90年代NeXT上有一个系统,它的工作方式如下:它们跟踪已分配的每个C / C ++内存块。它们会定期扫描内存,以查看是否存在与该内存地址关联的4字节(或8字节)值。如果不是,他们认为没有引用,他们释放内存。这很简单!但有时它搞砸了。
答案 2 :(得分:1)
你的意思是smart_ptr吗?
答案 3 :(得分:0)
它是用C而不是C ++编写的,并不是C ++的完美匹配,因为它不会调用析构函数,但可能会或多或少地符合这个要求。
答案 4 :(得分:0)
当然可以,为什么不呢?从垃圾收集器的角度来看,指针算法与索引到数组没有什么不同。它就像xor双向链表一样搞砸了GC,但这不是指针算术,也不是未定义的行为。此外,Boehm存在,这是一种经验证据,它是一个适用于C ++的垃圾收集器。他们有一段时间,他们威胁要将GC作为C ++ 0x的可选部分。
答案 5 :(得分:0)
问题是你为什么? 90%的时间你认为垃圾收集会很好,一个智能指针向量(如在一个向量/地图中删除它时删除对象)就足够了。其余的10%可以通过使用ref计数接口来处理。
答案 6 :(得分:0)
C ++指针算法允许你构造N + 1个指向T [N],& T [0] ...& T [N-1]和一个哨兵& T [N-1] +的指针1。这些都是指向T [N]数组对象的指针。从这个意义上说,它们类似于其他“内部”指针,例如& foo.bar(对象成员的地址)。
其他指针算法是未定义的行为,UB的一个明显例子可能是GC无意中删除了数组。
答案 7 :(得分:-1)
是的,GC可以独立于类型安全来实现,C ++在很大程度上没有;但GC可用的优化机会将受到语言允许的类型余地的限制。
如果一个人愿意接受运行时检查指针操作,从而在语言放弃的情况下重新实现类型安全,那么GC可以更加积极。事实上,垃圾收集C ++通常仅限于保守的收集器,如Boehm-Demers-Weiser GC。
答案 8 :(得分:-2)
我不是GC实现方面的专家,但是如果你允许使用指针运算,那么你就不能确定内存中的给定地址不能再被引用了。
作为例子
int *crazy_pointer;
srand ( time(NULL) );
while(true) {
crazy_pointer = (int *) rand() % MAX_SIZE_OF_MEMORY:
printf("$d",*crazy_pointer);
}
实际上,我已经以非常基本的方式使用指针算法来打印出内存中随机位置的内容。这意味着机器上的所有内存都必须是可访问的。如果可以到达,则无法进行GC。
是的,上述内容可能会导致现代操作系统崩溃,但此代码完全合法的C / C ++。如果允许指针算法,则无法实现可以防止此类滥用的GC:)