何时使用-retainCount?


110

我想知道您-retainCount到目前为止在什么情况下使用过,最终会发现使用它可能发生的问题。

谢谢。


5
你应该从来没有用户-retainCount
Holex

3
(除非您应有的时候。帮助您了解正在发生的事情有时非常有用,只要您意识到它有时可能会引起严重误导。当然,如果使用ARC,则完全不允许这样做。)
Hot Licks

Answers:


243

您永远不要使用-retainCount,因为它永远不会告诉您任何有用的信息。Foundation和AppKit / UIKit框架的实现是不透明的。您不知道要保留的内容,为什么要保留它,谁要保留它,何时保留它,等等。

例如:

  • 你会认为[NSNumber numberWithInt:1]将有一个retainCount1。事实并非如此。是2
  • 你会认为@"Foo"将有一个retainCount1。事实并非如此。是1152921504606846975。
  • 你会认为[NSString stringWithString:@"Foo"]将有一个retainCount1。事实并非如此。同样,它是1152921504606846975。

基本上,由于任何事物都可以保留对象(并因此改变其retainCount),并且由于您没有运行应用程序的大多数代码的源代码,因此对象的retainCount意义不大。

如果您尝试查找为什么未释放对象的原因,请使用仪器中的“泄漏”工具。如果您试图找出为什么对象被过早释放的原因,请使用Instruments中的“僵尸”工具。

但不要使用-retainCount。这是一种毫无价值的方法。

编辑

请所有人访问http://bugreport.apple.com并要求-retainCount弃用。要求的人越多越好。

编辑#2

作为更新,[NSNumber numberWithInt:1]现在retainCount的代码为9223372036854754775807。如果您的代码期望它是2,则您的代码现在已损坏。


4
感谢@ Dave-Delong提供的示例。
Moszi 2011年

1
目前,retainCount对单身人士很有用。(现在的问题是单身人士有多有用...)- (NSUInteger)retainCount{return NSUIntegerMax;}

8
@Joe可以使单身人士不占优势retainCount
Dave DeLong

5
@Joe我知道这一点;谷歌“ objective-c singleton”讨论了为什么该示例不是一个很好的例子。
Dave DeLong

2
我使用的一件事-@DaveDeLong,您可能也会发现这个错误,但我不这么认为-是覆盖dealloc和init并将NSLogs放入其中(即使使用ARC)。这给我的对象是否越来越dealloced或不是一个好主意,这就是我们通常试图回答真正的问题..
丹Rosenstark

50

决不!

说真的 只是不要这样做。

只需按照内存管理准则,只有释放你allocnew或者copy(或任何你叫retain后最初)。

@bbum 在SO上说得最好,在他的博客上更详细。


8
因为您会认为自己正在计数内存,但是这样做会出错。
阿比森2011年

@Abizern-另一个答案中的单身情况又如何呢?
Moszi 2011年

3
除此之外,您可以-retainCount从Instruments及其工具中获得(更详细的信息)您可以获得的任何信息。
Dave DeLong

3
加上戴夫所说的话;对象的绝对保留数是实现细节。对象内部的细节和/或对象可能已通过的任何其他对象的细节。调用retainretainretainautorelease, 自动释放,autorelease可能是传递对象通过的UIKit API,例如一个完全有效的结果。
bbum 2011年

2
@ d11wtq如果retainCount曾经== 0,则已达到奇点!
bbum 2011年

14

自动发布的对象是一种情况,其中检查-retainCount不能提供信息,并且可能会引起误解。保留计数不会告诉您对一个对象调用-autorelease多少次,因此什么也不会告诉您当前自动释放池耗尽时将释放多少次。


1
谢谢-这是一个好点。这是第一个答案,实际上有一个描述为什么除了通用的“不”之外不使用retainCount的原因。
Moszi 2011年

1
@Moszi:您的问题是“何时使用retainCount?” —如果您不想问这个问题,那您应该问其他问题。
查克(Chuck)

@chuck-实际上我对“何时使用它”感兴趣,但是似乎每个答案都将是“从不” ...但是-我想你是对的。我将把问题悬而未决几天,如果没有其他答案,那就再也没有了,那么我将接受“从不”作为答案。
Moszi 2011年

10

使用'Instruments'进行检查时,我确实发现keepCounts非常有用。

使用“分配”工具,确保“记录引用计数”已打开,并且您可以进入任何对象并查看其keepCount历史记录。

通过将分配和释放配对,可以很好地了解正在发生的事情,并经常解决那些没有释放某些东西的困难情况。

这从未让我失望过-包括在iOS的早期Beta版本中发现错误。


5

看看关于NSObject的Apple文档,它几乎涵盖了您的问题: NSObject keepCount

简而言之,除非您已实现自己的引用计数系统(而且我几乎可以保证您不会拥有),否则retainCount对您可能毫无用处。

用苹果自己的话来说,retainCount“在调试内存管理问题中通常没有任何价值”。


首先谢谢您的回答。通常人们对这个问题的反应是“从不”。(请参阅答案)。实际上,“调试中没有价值”并不意味着“从不”。所以我的问题是–为什么强烈不使用它(例如在单例实现中-再次是答案之一)?
Moszi 2011年

我想您需要提供有关其用途的更多信息。如Apple所建议的那样,可以接受的用法是重写keepCount来实现自己的引用计数系统。但是实际上,您永远不会看到(无论如何,我永远不会看到)。强烈的反应通常来自苹果自己提倡的事实(在他们的邮件组,文档,开发论坛等),他们不愿保留keepCount。
lxt 2011年

1
@Moszi:调试是大多数人可以想到的唯一有价值的情况,因此,如果在那里不可靠,它就永远不会有用。您还在考虑其他用途吗?
查克(Chuck)

4

当然,您永远不要在代码中使用keepCount方法,因为其值的含义取决于对对象应用了多少个自动发布,而这是您无法预测的。但是,它对于调试非常有用-尤其是当您在主事件循环外部调用Appkit对象的方法的代码中查找内存泄漏时-不应弃用它。

在表达自己的观点时,您严重夸大了价值的难以理解的本质。的确,它并不总是引用计数。有一些用于标志的特殊值,例如,指示永远不要释放对象。像1152921504606846975这样的数字看起来非常神秘,直到您用十六进制编写它并获得0xfffffffffffffff。并且9223372036854775807为十六进制的0x7fffffffffffffffff。假设您每秒增加了100,000,000次,假设某人将近300年才能获得与较大数字一样高的keepCount,那么有人选择使用诸如此类的值作为标志确实并不奇怪。


3

使用它会遇到什么问题?它所做的只是返回对象的保留计数。我从没打电话过,也没有想过的任何理由。我以单例方式覆盖了它,以确保它们不会被释放。


2
在单例情况下没有理由覆盖它。Foundation / CoreFoundation中没有retainCount用于内存管理的代码路径。
bbum 2011年

不释放使用它来决定是否应调用dealloc吗?
ughoavgfhw 2011年

2
不; 保留/释放/自动释放的内部实现在CoreFoundation中具有很深的渊源,实际上根本不符合您的期望。快去获取CoreFoundation的源代码(可以使用)并看看。
bbum 2011年

3

在您的应用程序启动并运行并执行有用的操作之前,您不必担心内存泄漏。

一旦完成,请启动Instruments并使用该应用,然后查看是否确实发生了内存泄漏。在大多数情况下,您自己创建了一个对象(因此您拥有它),并在完成后忘记释放它。

请勿在编写代码时尝试优化代码,而在正常使用该应用程序时,对于可能导致内存泄漏或时间太长的猜测常常是错误的。

请尝试编写正确的代码,例如,如果您使用alloc等创建对象,那么请确保正确释放它。


0

您永远不要在代码中使用它,但是在调试时绝对可以帮助您


0

切勿在代码中使用-retainCount。但是,如果使用,则永远不会看到它返回零。想一想为什么。:-)


0

Dave帖子中使用的示例是NSNumber和NSStrings ...因此,如果您使用其他类(例如UIViews),我敢肯定您会得到正确的答案(保留数取决于实现,这是可以预测的)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.