本文介绍了调用-retainCount被视为有害的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这篇文章旨在征求关于臭名昭着方法 retainCount 的详细记录,以便整合SO周围浮动的相关信息。 p>


  1. 基本信息:不使用 retainCount 的官方原因是什么?是否有任何情况 当它可能是有用的?应该做什么?**随意编辑。


  2. 历史/解释:Apple为什么在(如果不是)打算使用? Apple的代码是否依赖于 retainCount 用于某些目的?如果是,为什么不隐藏在某处?


  3. 为了更深入的理解:一个对象可能有不同的保留计数,假设从用户代码?你能给出任何框架代码可能使用的标准过程的示例***引起这样的差异吗?是否有任何已知的情况,其中保留计数始终与新用户可能期望的不同?


  4. 值得关注 retainCount










$我希望这将变成一个常见问题,一个很好的信息论文/讲座的任何我们的专家谁倾向于写一页,新的可可头可以指向当他们想知道 retainCount





解决方案

自动释放管理是最明显的 - 你没有办法确保由 retainCount 表示的引用中有多少在本地或外部(在辅助线程或在另一线程的本地池中)自动释放池。



另外,有些人有泄漏的麻烦,在更高级别的引用计数和自动释放池如何工作在基本水平。他们将写一个程序没有(很多)考虑正确的引用计数,或没有学习ref计数正确。这使得他们的程序很难调试,测试和改进 - 它也是一个非常耗时的整改。



阻止其使用的原因(在客户端级别)是双重的:



1)值可能因为这么多原因而有所不同。 单独的线程是足够信任它的原因。



2)您仍然需要实现正确的引用计数。 retainCount 永远不会从不平衡的引用计数中救出您。

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



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



在极少数情况下,这可能是一个有用的诊断。它可以用于检测:




  • 过度保留:保留计数不正确的分配不会显示为


  • 许多其他对象引用的对象:这个问题的一个例子是一个(mutable)共享资源或集合在多线程环境中运行 - 频繁访问或对此资源/集合的更改可能会在程序执行中引入严重的瓶颈。


  • 自动发布级别:自动释放,自动释放池和保留/自动释放循环都有成本。如果您需要最小化或减少内存使用和/或增长,您可以使用此方法检测过多的病例。




从与Bavarious的评论(下面):一个高值也可能表示无效的分配(dealloc'd实例)。这完全是一个实现细节,并且在生产代码中不可用。

如果你不负责返回 self 的内存(即你没有写一个分配器)



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



理解释放和自动释放使用,设置一些断点并了解它们的使用方式,在什么情况下等等。你仍然需要学习使用引用计数正确,但这可以帮助你理解为什么它是无用的。 p>

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

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



1)在托管环境中适当的引用计数。分配器可以使用 retainCount - 真的很好。这是一个非常简单的概念。当调用 - [NSObject release] 时,可以调用ref计数器(除非重写),如果 retainCount 为0(调用dealloc之后)。这在分配器级别是很好的。分配器和区域(在很大程度上)是抽象的,所以...这使得结果对于普通客户来说是无意义的。有关为什么 retainCount 在客户端级别,对象取消分配,取消分配序列等中不能等于0的详细信息,请参见使用bbum的注释(下面)。



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

和不朽的对象。 NSCFString 文字属于后一类:

  NSLog qu,[@MyStringretainCount]); 
// Logs:1152921504606846975



它没有用作调试助手。学习使用泄漏和僵尸分析,并经常使用它们,即使

有引用计数的处理。






更新: bbum最近发布了一篇题为。该文章详细讨论了为什么 -retainCount 在绝大多数情况下不起作用。


Or, Why I Didn't Use retainCount On My Summer Vacation

This post is intended to solicit detailed write-ups about the whys and wherefores of that infamous method, retainCount, in order to consolidate the relevant information floating around SO.*

  1. The basics: What are the official reasons to not use retainCount? Is there ever any situation at all when it might be useful? What should be done instead?** Feel free to editorialize.

  2. 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?

  3. 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?

  4. Anything else you think is worth metioning about retainCount?


解决方案

Autorelease management is the most obvious -- you have no way to be sure how many of the references represented by the retainCount are in a local or external (on a secondary thread, or in another thread's local pool) autorelease pool.

Also, some people have trouble with leaks, and at a higher level reference counting and how autorelease pools work at fundamental levels. They will write a program without (much) regard to proper reference counting, or without learning ref counting properly. This makes their program very difficult to debug, test, and improve -- it's also a very time consuming rectification.

The reason for discouraging its use (at the client level) is twofold:

1) The value may vary for so many reasons. Threading alone is reason enough to never trust it.

2) You still have to implement correct reference counting. retainCount will never save you from imbalanced reference counting.

You could in fact use it in a meaningful way if you wrote your own allocators or reference counting scheme, or if your object lived on one thread and you had access to any and all autorelease pools it could exist in. This also implies you would not share it with any external APIs. The easy way to simulate this is to create a program with one thread, zero autorelease pools, and do your reference counting the 'normal' way. It's unlikely that you'll ever need to solve this problem/write this program for anything other than "academic" reasons.

As a debugging aid: you could use it to verify that the retain count is not unusually high. If you take this approach, be mindful of the implementation variances (some are cited in this post), and don't rely on it. Don't even commit the tests to your SCM repository.

This may be a useful diagnostic in extremely rare circumstances. It can be used to detect:

  • Over-retaining: An allocation with a positive imbalance in retain count would not show up as a leak if the allocation is reachable by your program.

  • An object which is referenced by many other objects: One illustration of this problem is a (mutable) shared resource or collection which operates in a multithreaded context - frequent access or changes to this resource/collection can introduce a significant bottleneck in your program's execution.

  • Autorelease levels: Autoreleasing, autorelease pools, and retain/autorelease cycles all come with a cost. If you need to minimize or reduce memory use and/or growth, you could use this approach to detect excessive cases.

From commentary with Bavarious (below): a high value may also indicate an invalidated allocation (dealloc'd instance). This is completely an implementation detail, and again, not usable in production code. Messaging this allocation would result in a error when zombies are enabled.

If you're not responsible for returning the memory at self (that is, you did not write an allocator), leave it alone - it is useless.

You have to learn proper reference counting.

For a better understanding of release and autorelease usage, set up some breakpoints and understand how they are used, in what cases, etc. You'll still have to learn to use reference counting correctly, but this can aid your understanding of why it's useless.

Even simpler: use Instruments to track allocs and ref counts, then analyze the ref counting and callstacks of several objects in an active program.

We can assume that it is public for two primary reasons:

1) Reference counting proper in managed environments. It's fine for the allocators to use retainCount -- really. It's a very simple concept. When -[NSObject release] is called, the ref counter (unless overridden) may be called, and the object can be deallocated if retainCount is 0 (after calling dealloc). This is all fine at the allocator level. Allocators and zones are (largely) abstracted so... this makes the result meaningless for ordinary clients. See commentary with bbum (below) for details on why retainCount cannot be equal to 0 at the client level, object deallocation, deallocation sequences, and more.

2) To make it available to subclassers who want a custom behavior, and because the other reference counting methods are public. It may be handy in a few cases, but it's typically used for the wrong reasons (e.g. immortal singletons). If you need your own reference counting scheme, then this family may be worth overriding.

Again, a custom reference counting schemes and immortal objects. NSCFString literals fall into the latter category:

NSLog(@"%qu", [@"MyString" retainCount]);
// Logs: 1152921504606846975

It's useless as a debugging aid. Learn to use leak and zombie analyses, and use them often -- even after you have a handle on reference counting.


Update: bbum has recently posted an article entitled retainCount is useless. The article contains a thorough discussion of why -retainCount isn’t useful in the vast majority of cases.

这篇关于调用-retainCount被视为有害的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 14:00