Rav*_*mer 28 c garbage-collection
我听说C自动收集垃圾是不是最理想的 - 这有什么道理吗?
是否有特定原因没有为C实现垃圾收集?
R..*_*R.. 55
不要听"C老了,这就是为什么它没有GC"的人.GC存在一些基本问题无法克服,这使得它与C不兼容.
最大的问题是准确的垃圾收集需要能够扫描内存并识别遇到的任何指针.某些更高级语言限制整数不使用所有可用位,因此可以使用高位来区分对象引用和整数.然后,这些语言可以在特殊的字符串区域中存储字符串(可以包含任意八位字节序列),在这些区域中它们不能与指针混淆,并且一切都很好.但是,AC实现不能这样做,因为字节,更大的整数,指针和其他所有内容可以一起存储在结构,联合或作为返回的块的一部分malloc.
如果您丢弃准确度要求并决定一些对象永远不会被释放,那会怎么样?因为程序中的某些非指针数据与这些对象的地址具有相同的位模式?现在假设您的程序从外部世界(网络/文件/等)接收数据.我声称我可以让你的程序泄漏任意数量的内存,并最终耗尽内存,只要我能够猜出足够的指针并在我为程序提供的字符串中模拟它们.如果您应用De Bruijn序列,这会变得更容易.
除此之外,垃圾收集速度很慢.你可以找到数百名喜欢以其他方式声称的学者,但这不会改变现实.GC的性能问题可分为3大类:
现在声称GC很快的人只是将它与错误的东西进行比较:写得不好的C和C++程序每秒分配和释放数千或数百万个对象.是的,这些也会很慢,但至少可以预测,如果有必要可以测量和修复.一个编写良好的C程序将花费很少的时间malloc/ free开销甚至无法衡量.
Jer*_*fin 26
垃圾收集已被实施了C(例如,勃姆-德默斯-韦瑟集电极).出于多种原因,C未被指定为包含GC,主要是因为他们所针对的硬件和他们正在构建的系统,它只是没有多大意义.
编辑(回答一些其他提出的指控):
为了使保守的GC定义良好,你基本上只需对语言进行一次更改:说任何使指针暂时"不可见"的行为都会导致未定义的行为.例如,在当前的C中,您可以将指针写入文件,覆盖内存中的指针,稍后将其读回,并且(假设它之前有效)仍然可以访问它指向的数据.GC不一定"意识到"指针存在,因此它可以看到内存不再可访问,因此可以打开收集,因此后来的解引用不会"起作用".
至于垃圾收集是非确定性的:有实时收集器是绝对确定的,可用于硬实时系统.还有确定性的堆管理器用于手动管理,但大多数手动管理器不是确定性的.
至于垃圾收集缓慢和/或破坏缓存:从技术上讲,这是真的,但它纯粹是一种技术性.虽然(至少大多数情况下)避免这些问题的设计(例如,代际清除)是众所周知的,但可以认为它们并不完全是垃圾收集(尽管它们对程序员来说几乎完全相同).
对于在未知或意外时间运行的GC:与手动管理的内存相比,这不一定或多或少.您可以在一个单独的线程中运行GC,该线程运行(至少在某种程度上)是不可预测的.通过手动内存管理来合并空闲块也是如此.分配内存的特定尝试可能会触发收集周期,导致某些分配比其他分配慢得多; 使用惰性块的惰性合并的手动管理器也是如此.
奇怪的是,GC 与C++的兼容性远远低于 C++.大多数C++依赖于确定性地调用析构函数,但垃圾收集不再是这种情况.这打破了许多代码 - 编写代码越好,它通常会导致更大的问题.
同样,C++要求std::less<T>为指针提供有意义的(更重要的是,一致的)结果,即使它们指向完全独立的对象.使用复制收集器/清道夫需要一些额外的工作来满足这个要求(但我很确定它是可能的).处理(例如)某人散列地址并期望获得一致结果更加困难.这通常是一个糟糕的想法,但它仍然可能,并应产生一致的结果.
win*_*aed 18
C是在20世纪70年代早期发明的,用于编写操作系统和其他低级内容.垃圾收集器在附近(例如,Smalltalk的早期版本),但我怀疑他们是否能够在如此轻量级的环境中运行,并且使用非常低级别的缓冲区和指针会有所有复杂性.
Cro*_*yer 16
对不起,但是说C没有GC,因为它已经老了,或者因为它是针对不同的硬件而设计的,这有点荒谬.
问为什么C没有GC,但是其他语言有点像问"为什么锤子有一个钝端,而斧头有一个尖锐的结束"?嗯,语言是工具,不同的工具意味着构建具有不同要求的不同程序.某些程序(如设备驱动程序或操作系统内核)的要求几乎不可能实现垃圾收集,同时仍然满足它们,因此需要像C这样的语言,因此创建了C语言.
就像其他工具一样,它就是这样,因为它要解决的问题迫使它成为那样.说这是因为它是在70年代创建的,或者是因为旧的硬件使得它看起来像完全是间接的.如果这是真的,C会在70年代消失,但它仍然是一种流行的语言.
此外,如果没有某种运行时系统,gc很难干净地实现,但C意味着可以在裸硬件上运行.
wll*_*cnt 11
C是一种非常古老的语言,缺乏许多现代语言的钟声和哨声.要添加垃圾收集,现在需要重新调整语言.一般来说,任何愿意对C进行许多更改的人都会创建自己的语言.
将自动垃圾收集添加到语言上通常会降低性能,或者会导致垃圾收集在非常时间发生.将垃圾收集添加到C会导致它失去其中一个比较优势,因为它可以用于需要实时或接近实时响应时间的系统级编程.
作为一种语言,C被故意设计为非常小.它具有很少的内在操作或功能,其中大多数反映了CPU中的基本指令.它通常被称为"可移植汇编语言".
这使得编写可移植程序以切换电话呼叫变得非常好,这些程序在内存很少的小型计算机上运行,这是贝尔实验室在他们第一次使用C和Unix时70年代早期的一部分.
这也使C非常适合编写OS内核,设备驱动程序等.这样的可执行文件不能指望拥有丰富,复杂的运行时环境,如垃圾收集 - 甚至只是动态内存分配,如malloc().那是因为它们实际上构成了这些环境的基础,所以你会遇到"通过你的引导拉动自己"的问题.
人们已经为C编写了垃圾收集的内存分配库.但是库并不是C语言本身的一部分,而且复杂的东西也不太可能被接受为标准C库的一部分.C程序员对标准的更改非常保守.
| 归档时间: |
|
| 查看次数: |
2911 次 |
| 最近记录: |