gpt4 book ai didi

objective-c - 调用 -retainCount 被认为是有害的

转载 作者:IT老高 更新时间:2023-10-28 11:46:59 24 4
gpt4 key购买 nike

或者,为什么我没有使用 retainCount在我的暑假

这篇文章旨在征集关于这种臭名昭著的方法的原因和原因的详细文章,retainCount ,以整合围绕 SO.* float 的相关信息。

  • 基础知识:不使用的官方原因是什么retainCount ?有没有什么情况可能有用?应该怎么做?** 随意编辑。
  • 历史/解释:为什么 Apple 在 NSObject protocol 中提供这种方法如果不打算使用它? Apple 的代码是否依赖于 retainCount出于某种目的?如果是这样,为什么不把它藏在某个地方?
  • 为了更深入地理解:对象可能具有与用户代码假设不同的保留计数的原因是什么?您能否举出框架代码可能使用的导致这种差异的标准过程的任何示例***?是否有任何已知情况下保留计数总是与新用户可能期望的不同?
  • 关于 retainCount 您认为值得一提的其他任何事情?


  • *
    不熟悉 Objective-C 和 Cocoa 的编码人员经常会遇到或至少误解引用计数方案。教程解释可能会提到保留计数,当您拨打 retain 时,保留计数(根据这些解释)会增加一。 , alloc , copy等,并在您拨打 release 时减一(并且在将来的某个时刻,当您调用 autorelease 时)。

    因此,崭露头角的 Cocoa 黑客 Kris 可以很容易地想到检查对象的保留计数对于解决一些内存问题很有用,而且,瞧,每个对象上都有一个名为 retainCount 的方法可用。 !克里斯打电话 retainCount在几个物体上,这个太高了,那个太低了,这到底是怎么回事?!所以 Kris 在 SO 上发了一个帖子,“我的内存管理有什么问题?”然后一大群 字母下降说“不要那样做!你不能依赖结果。”,这很好,但我们勇敢的编码员可能需要更深入的解释。

    我希望这将变成一个常见问题解答,一页来自我们的任何一位愿意撰写的专家的优秀信息文章/讲座,当他们想知道 retainCount 时,可以指向新的 Cocoa 头。 .

    ** 我不想把它说得太宽泛,但是来自经验的特定提示或有关验证/调试保留和发布配对的文档可能适合这里。

    ***在虚拟代码中;显然,公众无法访问 Apple 的实际代码。

    最佳答案

    The basics: What are the official reasons to not use retainCount?



    自动释放管理是最明显的——你无法确定 retainCount 代表了多少引用。位于本地或外部(在辅助线程上,或在另一个线程的本地池中)自动释放池。

    此外,有些人在泄漏、更高级别的引用计数以及自动释放池如何在基本级别工作时遇到问题。他们将编写一个程序而不(很多)考虑正确的引用计数,或者没有正确学习引用计数。这使得他们的程序很难调试、测试和改进——这也是一个非常耗时的纠正。

    不鼓励使用它(在客户端级别)的原因有两个:

    1) 由于多种原因,该值可能会有所不同。 线程本身就足以让我们永远不要相信它。

    2)您仍然必须实现正确的引用计数。 retainCount永远不会使您免于不平衡的引用计数。

    Is there ever any situation at all when it might be useful?



    如果您编写自己的分配器或引用计数方案,或者如果您的对象存在于一个线程上并且您可以访问它可能存在的任何和所有自动释放池,那么您实际上可以以一种有意义的方式使用它。这也意味着您不会与任何外部 API 共享它。模拟这一点的简单方法是创建一个具有一个线程、零自动释放池的程序,并以“正常”方式进行引用计数。除了“学术”原因之外,您不太可能需要解决这个问题/编写这个程序。

    作为调试帮助:您可以使用它来验证保留计数是否异常高。如果您采用这种方法,请注意实现差异(本文中引用了一些差异),不要依赖它。甚至不要将测试提交到您的 SCM 存储库。

    在极少数情况下,这可能是一种有用的诊断方法。它可用于检测:
  • 过度保留:如果您的程序可以访问分配,则保留计数正不平衡的分配不会显示为泄漏。
  • 一个被许多其他对象引用的对象:这个问题的一个例子是在多线程上下文中运行的(可变)共享资源或集合 - 对该资源/集合的频繁访问或更改可能会在您的程序执行中引入重大瓶颈。
  • 自动释放级别:自动释放、自动释放池和保留/自动释放周期都有成本。如果您需要最小化或减少内存使用和/或增长,您可以使用此方法来检测过多的情况。

  • 来自 Bavarious 的评论(如下):高值也可能表示无效的分配(dealloc'd 实例)。这完全是一个实现细节,同样,不能在生产代码中使用。启用僵尸时,向此分配发送消息会导致错误。

    What should be done instead?



    如果您不负责在 self 处返回内存(也就是说,你没有写一个分配器),不管它——它没用。

    你必须学习正确的引用计数。

    为了更好地理解 release 和 autorelease 的用法,设置一些断点并了解它们是如何使用的,在什么情况下使用等。您仍然需要学习正确使用引用计数,但这可以帮助您理解为什么它没有用.

    更简单:使用 Instruments 来跟踪分配和引用计数,然后分析事件程序中几个对象的引用计数和调用堆栈。

    Historical/explanatory: Why does Apple provide this method in the NSObject protocol if it's not intended to be used? Does Apple's code rely on retainCount for some purpose? If so, why isn't it hidden away somewhere?



    我们可以假设它是公开的,主要有两个原因:

    1) 在托管环境中正确的引用计数。分配器可以使用 retainCount - 真的。这是一个非常简单的概念。当 -[NSObject release]被调用,引用计数器(除非被覆盖)可能会被调用,如果 retainCount 对象可以被释放是 0(在调用 dealloc 之后)。在分配器级别这一切都很好。分配器和区域被(大部分)抽象了......这使得结果对于普通客户端毫无意义。有关原因的详细信息,请参阅 bbum 的评论(下方) retainCount在客户端级别、对象释放、释放序列等中不能等于 0。

    2) 使其可用于想要自定义行为的子类,并且因为其他引用计数方法是公共(public)的。在少数情况下它可能很方便,但它通常用于错误的原因(例如不朽的单例)。如果您需要自己的引用计数方案,那么这个系列可能值得重写。

    For deeper understanding: What are the reasons that an object may have a different retain count than would be assumed from user code? Can you give any examples*** of standard procedures that framework code might use which cause such a difference? Are there any known cases where the retain count is always different than what a new user might expect?



    再次,自定义引用计数方案和不朽对象。 NSCFString文字属于后一类:
    NSLog(@"%qu", [@"MyString" retainCount]); 
    // Logs: 1152921504606846975

    Anything else you think is worth mentioning about retainCount?



    它作为调试辅助工具毫无用处。学习使用泄漏和僵尸分析,并经常使用它们——即使在您掌握了引用计数之后。

    更新: bbum 最近发表了一篇题为 retainCount is useless 的文章.这篇文章详细讨论了为什么 -retainCount在绝大多数情况下没有用。

    关于objective-c - 调用 -retainCount 被认为是有害的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5784084/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com