【问题标题】:Memory management - C# VS Objective C?内存管理 - C# VS Objective C?
【发布时间】:2010-09-09 02:37:23
【问题描述】:

所以我已经知道目标 C 中的内存管理,并且在使用 .net (C#) 编程时我从来不需要知道它。但我仍然对一切是如何完成的有一些疑问。

-如果我们分配一个对象而不释放它,为什么目标c中的代码会泄漏?

-为什么在 C# 中没有泄漏?

-自动垃圾收集有哪些优缺点?

-为什么不在每个分配的对象上使用自动释放(目标 C)?

-是否可以手动处理内存(C#)?所以假设我实例化了一个对象,当我完成后我想释放它,我不想等待垃圾收集器去做?

【问题讨论】:

  • 嗯,我似乎在与一群不知道 Objective-C 2.0 在 Mac 上进行垃圾收集的 iPhone 开发人员竞争。 en.wikipedia.org/wiki/Objective-C#Garbage_collection
  • :) 不,我认为他们的票数更高,因为他们以 1 对 1 的方式回答了问题 :)。但是知道mac上的objective c有垃圾收集器很有趣

标签: c# objective-c memory-management


【解决方案1】:
  • 它在 Objective-C 中泄漏,因为 Objective-C 没有对其采取任何操作。它依赖于你完成所有的工作。它不会在 C#(更准确地说,在 .NET)中泄漏,因为它使用了一个垃圾收集器来清理不再使用的对象。

  • 垃圾回收的主要优点是:内存泄漏要少得多。 (仍然有可能发生内存泄漏,例如无限期地填充列表,但这更难意外发生。)过去人们认为垃圾收集的缺点是它可能会减慢程序的速度,因为它一直在做垃圾在后台收集,您几乎无法控制它。然而实际上,差异可以忽略不计:您的计算机上还有其他后台任务(例如设备驱动程序)一直在运行,垃圾收集器也不会破坏骆驼的背部。

  • 自动释放(当非指针变量超出范围时在 C++ 中使用它)是危险的,因为它打开了对它的引用的可能性,即使在对象已被释放后仍然存在.如果您的代码随后尝试访问该对象,则该过程将大放异彩。

  • 是的,可以通过直接调用垃圾收集器 (GC.Collect()) 来告诉 C# 释放内存。但是,我还没有看到完全有必要这样做的案例。如果你真的用完了内存,垃圾收集器就会自动启动并尽可能多地释放。

【讨论】:

  • 你可以告诉垃圾收集器运行,但它只会收集它“应该”的东西——如果仍然有对它的引用,它就不会释放你的对象,也不应该.但 GC.Collect() 只是一个提示。它告诉垃圾收集器现在收集是实用的,因为我们可以处理延迟,但如果它认为没有太多工作要做,它可能会忽略你。
  • Mac 上的 Objective-C 也有一个垃圾收集器(此时 iPhone 上没有)。
【解决方案2】:

Objective-C 不是一种垃圾收集语言,因此它无法知道一个对象将不再被使用,除非你告诉它。这就是 .NET 垃圾收集器的目的:它检查哪些对象不能再被程序使用,并在某些时候摆脱它们以释放内存。无法保证何时或是否会释放任何给定的废弃对象;它只是试图防止内存使用失控。

没有垃圾收集器,C# 无法释放对象。如果你释放一个仍然被引用的对象,当你尝试使用它时你的程序将会崩溃。这始终是手动内存管理的风险,但就像所有“内存管理语言”一样,它试图阻止你犯那个错误。如果要显式关闭对象的操作,请为该对象的类型实现接口 IDisposable,并对该对象使用 Dispose() 方法——本质上是一个析构函数。当然,请确保您已经完成了它,并且如果在 Dispose()d 之后尝试使用它,则该对象将正常运行(通过引发异常)。

Objective-C 是引用计数的。当一个对象没有引用时,它会删除自己。对于“有人还在使用这个对象吗?”这不是一个糟糕的解决方案。问题,除了引用自身的数据结构;除非小心处理,否则循环数据结构将永远存在。 .NET 不是引用计数器,因此它将摆脱运行代码无法访问的循环数据结构。

据我所知,自动释放只是“稍后发布”,用于返回一个应该自毁的值,如果抓取它的代码不立即想要保留它。 (不过,我不是 Objective-C 程序员。)它绕过了“谁发布了这个对象?”返回对象的调用的问题,在函数完成之前没有销毁它。不过,这是一个特殊的用例,在大多数其他情况下没有意义。

【讨论】:

  • Autorelease 不仅可以用于返回值。它可用于清理函数中的代码,您不想在最后发布所有内容,或者您​​想创建变量并将其传递给另一个函数而不创建引用。开始时自动释放可能会很棘手,就好像你过度释放一个对象一样,它可能会导致稍后在代码执行中出现问题,可能不清楚问题的原因是什么。
  • 我不是 Objective-C 程序员,所以感谢您提供的信息!我想编辑我的最后一段以使其更有用。自动释放的真正作用是什么?出于某种原因,三分钟的浏览文档并没有带来完全的启发。 :-)
  • Objective-C 确实有一个垃圾收集器,但它只适用于 Mac OS X。
【解决方案3】:

自动垃圾回收的优点是您不必像您所说的那样显式地释放/释放您的对象。缺点是您无法确定何时(或什至)任何给定的对象实例会被释放。

C# 有其他机制来释放其他资源,如文件或必须确定释放的数据库连接。例如,using 允许您确保在对象上确实调用了 IDispose。

与经过良好调整的手动实施相比,垃圾收集系统在任何给定时间都倾向于使用更多内存。当然,你没有内存泄漏。

垃圾收集器的质量和性能可能会有很大差异,这是您可能无法控制的。例如,GC 运行时可能会有明显的延迟。在 .NET 中,您可以调用 GC.Collect() 告诉 GC 现在是个好时机,但它可能会也可能不会听。

如今,Objective-C 在 Mac 上也被垃圾收集了。在 iPhone 上它是引用计数的,所以我认为这就是您遇到问题的地方。

在垃圾回收系统上,您仍然会遇到对象挂在对您希望被垃圾回收的对象的引用的问题。垃圾收集器不会清理它,因此内存基本上是泄漏的。

在引用计数系统中,您不必跟踪指向对象实例的每个对象,但您必须指定要释放它们。

编辑:我想我并没有明确说出来——你不能在 C# 中手动控制内存分配。

【讨论】:

  • 从 c# 的角度来看,自动垃圾收集也会带来内存和速度损失——因为系统必须跟踪堆上的所有变量以及对它们的所有引用。此外,无法预测自动垃圾收集器何时运行(尽管可以调用),因此您会发现编写不佳的时序代码可能会受到垃圾收集器操作的不利影响。
  • @Tim - 我的回答已经提到 GC 具有内存影响,并且我谈到了 GC 实现的不同性能。我应该在答案中添加其他内容吗?
猜你喜欢
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2011-05-11
相关资源
最近更新 更多