【问题标题】:Use both Garbage Collector and ARC in objective c在目标 c 中同时使用垃圾收集器和 ARC
【发布时间】:2013-11-15 08:36:44
【问题描述】:

我读到垃圾收集是在目标 c 中使用 AUTOZONE(LIBAUTO) 完成的。

垃圾收集器也可用于 OS X 10.8。在学习时,我在想如果垃圾收集器可用,ARC 的需求是什么。然后从 stackoverflow.com 上的资源中,我了解了 ARC 和垃圾收集器之间的区别以及两者之间的优势。

现在我知道 ARC 在编译时工作,而垃圾收集器在运行时工作。 ARC 也不能释放 CFTypes 的内存,它只适用于目标 C 类型。垃圾收集器可以释放使用 ARC 无法完成的保留周期。

现在我想知道我们可以同时使用 ARC 和垃圾收集器,因为两者都在 os x 10.7 中可用。还有为什么垃圾收集器在 10.8 之后被弃用。 ARC 是垃圾收集器的替代品吗?它可以释放垃圾收集器完成的所有类型的对象。

另外由于垃圾收集器在 ios 中不可用,那么在 ARC 之前的 ios 中用于垃圾收集的东西。手动内存管理是否能够正确处理所有事情,如果手动内存管理处理得当,是否不需要垃圾收集?

【问题讨论】:

  • ARC 旨在成为垃圾收集器的卓越替代品。我不知道有任何官方方法可以同时使用它们,并且看不出你需要这个的理由。
  • 我不使用 ARC。在 ARC 出现之前,我已经开始在 Objective-C++ 中使用来自 C++ 的智能指针。它比 Apple 的 ARC 更好:它与旧的非弧形代码完美配合,并且不需要代码转换,并且在您的情况下可以与垃圾收集一起使用。所以我的建议:如果你熟悉 C++,那么最好使用智能指针而不是 ARC。
  • @Cy-4AH ARC 用于 Objective-C 内存管理,智能指针(如在 std::shared_ptr 中)用于 C++ 内存管理。您不会使用一个“代替”另一个,它们具有不同的角色。
  • 谢谢你们俩。我目前没有从事任何使用它的项目。只是在目标 c 中清除我的内存管理概念。
  • @Cy-4AH:另外,尝试自己重塑 std::shared_ptr 之类的东西肯定是出了问题的迹象:你真的认为自己一个人可以做得更好吗? 一群具有多年经验的其他专家?

标签: objective-c macos garbage-collection automatic-ref-counting


【解决方案1】:

据我所知,没有(简单的)方法可以同时启用这两者,而且无论如何也没有意义。

您自己几乎已经回答了这个问题:GC 和 ARC 的用途相同,都是清理内存。 GC 具有捕获 ARC 无法捕获的东西的优势,但它有运行时损失。使用 ARC,如果您没有正确使用它,您仍然可能会泄漏内存,但如果操作正确(主要是:您遵守命名约定),ARC 的主要优势在于通过出色的运行时性能将您从手动管理负担中解放出来。

所以你选择了一个或另一个,混合它们没有任何意义。如果您启用了 GC,ARC 所做的所有工作将几乎毫无用处,从而浪费性能。

顺便说一句,在 ARC 之前,我们使用 retain/release 进行手动内存管理。事实上,这仍然是一种选择,并且仍然被广泛使用(例如,我从事一个大型项目,转换为 ARC 会很麻烦)。

【讨论】:

  • @DarkDust “一个巨大的项目,转换为 ARC 会很麻烦” - 出于兴趣,您是否尝试过 XCode 的“转换为 ARC”工具,或者这对您不起作用?
  • @Merlin069:不幸的是,对于这个特定的项目来说,这并不容易,因为我们在某些领域会使用 ARC 禁止的技巧,并且移植它们需要一些工作。由于我们都是 ARC 之前的开发人员,所以这没什么大不了的。 Instruments 告诉我们没有泄漏,那么为什么要更改正在运行的系统呢? :-)
  • @DarkDust,感谢您的解释;我一直怀疑 Apple 代码是否会创建这样一个工具来满足每个项目 ;O)
【解决方案2】:

在 C 中,内存管理通常使用 malloc 和 free 来执行。 在 C++ 中,new 和 delete 是首选方法。这两者都依赖于开发人员确切地知道他们分配了哪些内存,在哪里(堆栈与堆),并且他们必须只处理一次释放该内存!

如果两个对象引用同一个对象,这会变得很尴尬;哪个负责清理该对象?

Objective-C 决定使用 retain /release 来解决这个问题,它管理对象的内部引用计数。当该计数为零时,该对象被删除并释放其内存。此方法通常由开发人员使用 C 和 C++ 手动实现,或使用智能指针自动实现。

着眼于 Objective-C 的发展,Apple 一直致力于通过自动化样板代码来使语言更易于使用且不易受常见错误的影响。

因此,手动处理保留和释放的下一步是 GC,但如前所述,运行时存在 GC 运行时间的开销。 GC 二进制文件与手动和自动 (ARC) 的引用计数完全不同且不兼容。这就是为什么在开发 System Preferences bundle 时,仍然必须启用 GC,因为宿主应用程序(System Preferences)继续使用 GC,即使在 Mavericks 中也是如此。忘记使用 GC 编译 3rd 方首选项包将导致包的加载失败。

ARC 的开发回归到保留/释放模型,但编译器会为开发人员处理此问题,从而使代码更易于编写和阅读。 Apple 很可能会继续沿着这条道路前进,而且我每年都希望 Objective-C 变得更加完善。

这就是能够定义编译器和它工作的语言的优势。

在我看来,这样做的不利之处在于,随着语言的发展,新接触该语言的开发人员更难找到不引用旧功能的文档,尤其是在网络上搜索示例代码时。试图破译导致的编译器错误对于刚接触 Objective-C 的开发人员来说是一个巨大的挫败感。

【讨论】:

    【解决方案3】:

    您不能混合使用 ARC 和 GC,因为 Objective-c 运行时不允许这样做,因为几个概念彼此不兼容:

    • GC 的工作方式是 -retain/release/autorelease/... 不再执行任何操作,为了弥补这一事实,引入了一个新概念,即 -finalize;
    • ARC 的工作方式是您不应该替换 -retain/release/autorelease,编译器会为您发布它们(而不是直接使用 [object retain],而是仅在您没有替换时才有效的较低级别的东西 -保留/释放/自动释放)。

    这些原因确实意味着 GC 和 ARC 的 ABI 非常不同,并且不兼容。

    ARC 和 MRR 是兼容的(您可以混合使用 ARC 构建的代码和使用标准 MRR 构建的代码); GC 和 MRR 是兼容的,因为基本上,如果您在 GC 模式下运行,MRR 调用将被忽略; 但 GC 和 ARC 不是。

    当我说运行时不允许它时,这意味着在运行时,如果加载框架的应用程序是在 GC 模式下运行的 GC 应用程序,那么任何框架都不能用 ARC 编写,因为它们不支持 GC并且无法为应用加载。

    作为副作用,这意味着支持 GC 的 Apple 框架要么使用 CF 或 MRR 编写,它们没有 ARC,可怜的灵魂。

    【讨论】:

    • 在撰写上述答案时我不确定,但实际上 Objective-C 运行时可以混合 ARC 和 GC 代码,但不能在同一个 image。例如,您可以在 ARC 程序上加载 GC 编译的共享库,也可以在 GC 程序上加载 ARC 编译的共享库。
    猜你喜欢
    • 2011-12-22
    • 2013-04-01
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多