8

我有纯ARC编码的经验。作为编译器功能,它尊重 Objctive-C 方法系列,在需要时放置正确的保留/释放调用。

所有以,开头的方法alloc,并创建一个新对象。它们增加了保留计数。因此,当我不再需要它时,ARC 将释放任何指针(以及与之关联的对象)。mutableCopycopynew

我认为当我编写不遵循命名约定的方法时可能会出现问题。例如,如果我newCustomer在第一个版本中编写这样的方法返回一个自动释放的对象,而在第二个版本中没有,会发生什么?

特别是,我的问题如下(它们属于相同的推理):

  • 如果调用和被调用的代码都用 ARC 编译会发生什么?
  • (a)如果调用代码使用 ARC 编译,而被调用代码使用非 ARC 编译,会发生什么情况?
  • (b)如果调用代码使用非 ARC 编译,而被调用代码使用 ARC 编译,会发生什么情况?

如果答案显示了 ARC 如何在幕后工作( , 等),我们将不胜objc_release感激objc_retainAutoreleasedReturnValue

先感谢您。

4

2 回答 2

12

命名的方法newCustomer属于new 方法族,因此被隐式标记为返回保留对象。当调用代码和被调用代码都使用 ARC 编译时,ARC 会平衡额外的保留与调用者中的释放:

从这样的函数或方法返回时,ARC 会在返回语句的求值点保留该值,然后再离开所有本地范围。

当从这样的函数或方法接收到返回结果时,ARC 会在包含它的完整表达式的末尾释放值,但要服从对局部值的通常优化。

来源

如果newCustomer使用手动引用计数实现并违反命名约定(即,不返回保留对象),则调用者可以根据情况过度释放或释放不足。

如果调用者使用 ARC,则返回的对象newCustomer将被过度释放 - 可能导致程序崩溃。这是因为调用代码将参与上述过程的后半部分,而在此之前没有执行相应的保留。

如果调用代码不是用 ARC 编译的,但被调用代码是(因此正确实现返回保留对象),那么行为取决于程序员遵循命名约定。如果他们释放返回值,那么对象的引用计数将被正确管理。但是,如果程序员认为他们的new...方法确实违反了命名约定,并且未能在调用代码中手动插入释放,则返回的对象将泄漏。

总而言之,正如 Martin R. 在评论中指出的那样,关键的决定是在包括手动引用计数在内的任何环境中是否遵循命名约定。

于 2013-04-01T16:53:57.010 回答
2

就像任何其他语言一样,当您违反该语言的一些基本假设时,您就会进入未定义行为的领域。在未来的某个时候,Apple 可能会修改-new...引用计数的内部结构。Apple 有责任确保符合预期用途的代码有效,但他们不会为不符合规定的用途这样做。

如果您需要知道在特定系统上运行的特定版本的编译器的实际行为是什么,那么您必须对其进行测试。不要假设其他编译器或运行时版本的行为相同。

最后,未定义的行为就是未定义的行为。当你构建依赖它的代码时,你最终会受到一个微妙且难以诊断的缺陷的影响。

于 2013-04-01T16:57:01.683 回答