为什么垃圾回收如此重要?

5

我不太理解垃圾回收,想知道为什么这对语言和开发者如此重要?


19
因为很少有人能够自己良好地进行内存管理。 - James Black
1
我喜欢那个。我也喜欢把它看作是现代编程的奢侈品,就像关联数组一样。 - toto
1
我很难同意这里的答案。我认为,通过一个良好建立的系统,你可以管理你的内存(即智能指针),而不需要变得“太技术化”或让逻辑远离你。 - MasterMastic
8个回答

20
许多其他答案已经说明了垃圾回收可以帮助预防内存泄漏,但是令人惊讶的是,没有人提到GC最重要的好处是促进内存安全。这意味着大多数垃圾回收环境完全抽象化了内存位置的概念(即原始指针),因此消除了一个重要的错误类别。
例如,手动内存管理的常见错误之一是意外地在稍微早一点的时候释放值,并在释放后继续使用该位置的内存。这可能极难调试,因为已释放的内存可能不会被重新分配,因此看似有效的操作可能在程序执行后期无规律地失败并出现损坏或内存访问违规或分段故障,通常与有问题的代码没有直接联系。这种错误类型在大多数垃圾回收环境中根本不存在。

作为一名前Delphi开发人员,我可以说:“完全同意!” - Kit
非常好的答案。我认为对于大多数可变对象而言,确定性处理与非确定性处理并没有太大区别,因为可变对象通常应该有一个明确定义的所有者,但即使是具有明确定义所有权的对象,确保非所有者引用无法访问游离内存也非常有价值。 - supercat
"由于可变对象通常应该有一个明确定义的所有者。如果您的程序使用具有可变边缘和顶点的图形,可以脱落不可访问的子图,然后这些子图就有资格进行收集,它们的“明确定义的所有者”将是谁?" - J D

6

垃圾回收是一种自动内存管理方式。它是资源管理的一种特殊情况,被管理的有限资源是内存。

对于程序员来说,垃圾回收的好处在于它解放了程序员手动处理内存分配和释放的工作。


释放内存可能会由系统自动处理,但是你仍然需要通过某种方式进行内存分配。 - foo

6
垃圾回收是许多现代语言的一部分,它试图通过减少开发人员的干预来抽象化内存的处理和重新分配。
当你听到“安全”对象的说法时,通常指的是在对象超出范围或显式销毁后,垃圾回收器可以自动重新分配其内存的东西。
虽然您可以编写没有垃圾回收器的相同程序来帮助管理内存使用,但将其抽象化可以让开发人员更多地考虑高级事物,并更快,更有效地为最终用户提供价值,而不必太关注程序的低级部分。
实质上,开发人员可以说:
给我一个新对象
.. 一段时间后,当对象不再被使用(超出范围)时,开发人员不必记得说:
扔掉这个对象
开发人员很懒(一个好习惯),有时会忘记事情。 当正确使用GC时,忘记清理垃圾没关系,垃圾回收器不会让它堆积并开始散发臭味。

2
关于你的句子"...开发人员不必记得说要丢弃这个对象":我不同意。为了丢弃一个对象,程序员使用赋值、程序中的内存覆盖和函数返回。不存在"不说丢弃对象"这样的事情。程序员是在说它,但大多数时候并不知道。垃圾回收之所以有效,是因为程序员编写的程序语句中大部分的对象丢弃都是自然地编码的。请注意,在某些情况下,程序员必须手动覆盖引用以帮助GC - user811773
6
非垃圾收集系统中的问题通常不是“忘记”丢弃对象造成的。相反,问题在于“最后一个离开房间的人,请关灯”的策略只有在那些离开房间的人能够轻松看到是否有其他人在场时才能很好地发挥作用。如果那些认为房间已经空无一人的人离开时关闭了灯,但实际上无法确定房间是否真的没有人,这是很危险的。定期让管理员锁门、检查是否有人在内,在确认房间已经无人之后再熄灭灯光可以更加安全。 - supercat

4

底线是 垃圾回收 有助于 防止内存泄漏。例如,在.NET中,当没有任何引用对象时,该对象使用的资源被标记为垃圾回收。在非托管语言(如C和C ++)中,开发人员需要负责清理。

然而,需要注意的是,垃圾回收并不完美。请看这篇文章,介绍了由于开发人员不知道存在大量内存泄漏而导致的问题。


2
GC确实有助于内存管理(您不必自己分配和释放内存),但不能防止内存泄漏。 - Pascal Thivent
1
这就是我试图通过加粗“helps”并链接到一个真实世界的例子来说明的,即它并不总是按预期工作。 - senfo

3
在许多老的、不太严格的语言中,程序员将内存释放编码到程序中是很困难的。如果没有正确地执行,这当然会导致问题,因为一旦引用未被释放的内存,你的程序就会崩溃。为了解决这个问题,垃圾回收机制应运而生,自动释放不再使用的内存。这种系统的好处显而易见:程序变得更加可靠,内存释放从设计过程中有效地消除,调试和测试时间大大缩短等等。
当然,没有免费的午餐。你失去的是性能,有时你会注意到程序中的不规则行为,虽然现在更先进的语言很少出现这种情况。这就是为什么许多典型的应用程序都是用Java编写的原因,它快速简单,不必追踪内存泄漏,完美适用于商业领域,由于今天计算机的速度非常快,性能损耗也很小。显然,一些行业需要管理他们自己程序中的内存(如游戏产业)出于性能原因,这就是为什么几乎所有主要的游戏都是用C++编写的原因。一位讲师曾告诉我,如果每个软件公司都在同一区域,并且中间有一家酒吧,你将能够从中分辨出游戏开发人员,因为他们会在深夜狂欢畅饮。

1

垃圾回收是一项必需功能,可以允许自动管理内存分配。这就是允许您分配各种对象,可能引用或包含这些对象的其他变量,并且永远不必担心处理对象(当它实际上不再使用时)。

垃圾回收特别负责“清理”堆,即所有这些对象所在的堆,通过删除未使用的对象并重新打包其他对象在一起。

您可能经常听到它,因为这是一个关键的函数,它异步地与程序发生,如果没有有效处理,可能会在程序中产生一些随机性能滞后等问题。然而,现在与内存管理相关的算法以及特别是垃圾回收算法相当高效。

GC有时提到的另一个原因是与某些特定对象的析构函数相关。由于应用程序无法(或很少)控制何时对特定对象进行垃圾回收(因此销毁),如果对象等待其析构函数来处理某些资源,则可能会出现问题。这就是为什么许多对象实现了Dispose()方法,该方法允许执行大部分清除(对象本身)的工作,而不是将其推迟到最终从GC逻辑调用析构函数时。


0
自动垃圾回收(如Java),会重复利用内存泄漏或不再使用的内存,使您的程序更高效。在C++中,您必须自己控制内存,如果您失去对某个内存的访问,那么该内存就无法再被使用,浪费了空间。这是我在一年的计算机科学学习和使用/学习Java和C++之后所了解到的。

-2

因为有些人可以像这样编写代码:

consume(produce())

而不必关心清理工作。就像在我们当前的社会中一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接