关于macos:在C中同时使用垃圾收集器和ARC

Use both Garbage Collector and ARC in objective c

我已经阅读过,垃圾收集是在目标C中使用autozone(libauto)完成的。

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

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

现在我想知道我们可以同时使用arc和垃圾收集器吗,因为这两种方法都可以在OSX10.7中使用。另外,为什么垃圾收集器在10.8之后被弃用。是垃圾收集器的替代品,它可以释放垃圾收集器完成的所有种类的对象。

另外,由于垃圾收集器在IOS中不可用,所以在ARC之前在IOS中用于垃圾收集的内容。如果操作正确,手动内存管理是否能够管理所有内容,如果正确处理手动内存管理,则不需要垃圾收集?


据我所知,没有(简单)的方法来实现两者,而且无论如何也没有意义。

您已经几乎自己回答了这个问题:GC和ARC都有相同的用途,可以清除内存。GC具有捕获ARC不能捕获的内容的优势,但它有运行时惩罚。有了ARC,如果您不正确地使用它,您仍然可以泄漏内存,但是如果正确地使用它(主要是:您遵守命名约定),ARC的主要优势是以优异的运行时性能将您从手动管理负担中解放出来。

所以你要么选择其中一个,要么选择另一个,把它们混合起来并没有什么意义。如果启用了GC,那么ARC所做的所有工作都将几乎是无用的,因此会浪费性能。

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


不能混合使用arc和gc,因为objective-c运行时不允许使用它,因为有几个概念彼此不兼容:

  • GC的工作方式是-retain/release/autorelease/…不再做任何事,为了弥补这个事实,一个新的概念被引入,这是-最后确定;
  • ARC的工作方式是,您不应该替换-retain/release/autorelease,编译器会为您发布它们(而不是直接使用[object retain],而是只在您没有替换-retain/release/autorelease时才起作用的较低级别的东西)。

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

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

当我说运行时不允许这样做时,这意味着在运行时,如果加载框架的应用程序是一个在gc模式下运行的gc应用程序,那么就不能用arc编写任何框架,因为这些框架不支持gc,并且不能为应用程序加载。

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


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

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

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

考虑到Objective-C的发展,苹果公司不断地通过自动化样板代码,使该语言更易于使用,并且不易受到常见错误的影响。

因此,手工处理RETAIN和RELEASE的下一步是GC,但正如前面提到的,运行时GC将运行时会有开销。gc二进制文件完全不同,并且与手工和自动(arc)的参考计数不兼容。这就是为什么在开发系统首选项包时,仍然必须启用GC,因为主机应用程序(系统首选项)继续使用GC,即使是在Mavericks中。忘记使用GC编译第三方首选项包将导致包的加载失败。

ARC的开发将恢复到RETAIN/RELEASE模型,但编译器会为开发人员处理这一问题,使代码更易于编写和读取。苹果很可能会继续沿着这条路走下去,每年我都希望Objective-C变得更精致。

这是能够定义编译器及其工作语言的优点。

在我看来,这样做的缺点是,随着语言的发展,新语言的开发人员很难找到不引用旧特性的文档,尤其是在搜索Web(例如代码)时。对于不熟悉Objective-C的开发人员来说,试图破译所导致的编译器错误可能是一个巨大的挫折源。