何时使用 -retainCount?

When to use -retainCount?

提问人:Moszi 提问时间:1/9/2011 最后编辑:Lorenzo BMoszi 更新时间:6/5/2018 访问量:25437

问:

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

谢谢。

Objective-C 内存管理 保留计数

评论

5赞 holex 5/4/2013
切勿使用 .-retainCount
3赞 Hot Licks 6/2/2013
(除非你应该这样做。偶尔帮助理解正在发生的事情是很有用的,只要您意识到它有时会产生严重的误导。而且,当然,如果使用 ARC,则根本不允许这样做。

答:

51赞 Abizern 1/9/2011 #1

从不!

认真地。只是不要这样做。

只需遵循内存管理指南,并且只发布您或(或您最初调用的任何内容)的内容。allocnewcopyretain

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

评论

8赞 Abizern 1/9/2011
因为你会认为你在计算内存,但你会做错。
0赞 Moszi 1/9/2011
@Abizern - 其他答案之一中的单例情况呢?
3赞 Dave DeLong 1/9/2011
除此之外,您可以从 Instruments 及其工具中获得(更详细的信息)的任何信息。-retainCount
3赞 bbum 1/9/2011
补充戴夫所说的话;对象的绝对保留计数是实现细节。对象内部的细节和/或对象可能经过的任何其他对象的细节。例如,调用 、 、 autorelease 可能是通过 UIKit API 传递对象的完全有效的结果。retainretainretainautorelease, autorelease
2赞 bbum 1/10/2011
@d11wtq 如果 retainCount ever == 0,则奇点已实现!
3赞 ughoavgfhw 1/9/2011 #2

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

评论

2赞 bbum 1/9/2011
在单例情况下,没有理由覆盖它。Foundation/CoreFoundation 中没有用于内存管理的代码路径。retainCount
0赞 ughoavgfhw 1/9/2011
发布不是用它来决定是否应该调用 dealloc 吗?
2赞 bbum 1/10/2011
不;retain/release/autorelease 的内部实现在 CoreFoundation 中有着深厚的根基,实际上完全不是你所期望的。去获取 CoreFoundation 源代码(可用)并查看。
5赞 lxt 1/9/2011 #3

看看 NSObject 上的 Apple 文档,它几乎涵盖了你的问题:NSObject retainCount

简而言之,retainCount 对你来说可能毫无用处,除非你已经实现了自己的引用计数系统(我几乎可以保证你不会这样做)。

用 Apple 自己的话来说,retainCount “在调试内存管理问题时通常没有价值”。

评论

0赞 Moszi 1/9/2011
首先,感谢您的回答。通常人们对这个问题的反应是“从不”。(见答案)。实际上,“调试中没有价值”并不意味着“从不”。所以我的问题是——为什么不使用它的强烈感觉(例如在单例实现中 - 再次成为答案之一)?
0赞 lxt 1/9/2011
我想你需要提供更多关于你使用它的信息。正如 Apple 所建议的那样,可接受的用法是覆盖 retainCount 来实现您自己的引用计数系统。但在实践中,你永远不会看到这一点(反正我从来没有)。强烈的反应通常来自苹果自己(在他们的邮件组、文档、开发论坛等中)主张不理会 retainCount。
1赞 Chuck 1/9/2011
@Moszi:调试是大多数人认为它有价值的唯一情况,所以如果它在那里不可靠,它就永远不会有用。你还想着什么其他用途?
3赞 ExitToShell 1/9/2011 #4

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

一旦成功,启动仪器并使用该应用程序,看看是否真的发生了内存泄漏。在大多数情况下,您自己创建了一个对象(因此您拥有它),并在完成后忘记释放它。

不要在编写代码时尝试优化代码,当您实际正常使用应用程序时,您对可能泄漏内存或花费太长时间的内容的猜测通常是错误的。

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

15赞 Jonah 1/9/2011 #5

自动释放的对象是检查 -retainCount 没有信息且可能具有误导性的一种情况。保留计数不会告诉您对象上调用了多少次 -autorelease,因此在当前自动释放池耗尽时将释放多少次。

评论

1赞 Moszi 1/9/2011
谢谢 - 这是一个很好的观点。这是第一个答案,除了通用的“不”之外,它实际上还描述了为什么不使用 retainCount 的原因。
1赞 Chuck 1/9/2011
@Moszi:你的问题是“什么时候使用retainCount?”——如果你不是故意问这个问题,你应该问别的问题。
0赞 Moszi 1/9/2011
@chuck - 实际上我对“何时使用它”很感兴趣,但是似乎每个答案都是“永远不会”......但是 - 我想你是对的。我会把这个问题搁置几天,如果除了“从不”之外没有答案,那么我将接受“从不”作为答案。
248赞 Dave DeLong 1/9/2011 #6

你永远不应该使用 ,因为它永远不会告诉你任何有用的东西。Foundation 和 AppKit/UIKit 框架的实现是不透明的;你不知道保留了什么,为什么保留了,谁保留了,何时保留,等等。-retainCount

例如:

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

基本上,由于任何内容都可以保留对象(因此可以更改其对象),并且由于您没有运行应用程序的大多数代码的源代码,因此对象的源代码毫无意义。retainCountretainCount

如果您尝试追踪对象未解除分配的原因,请使用 Instruments 中的“泄漏”工具。如果您试图追踪对象过早释放的原因,请使用 Instruments 中的 Zombies 工具。

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

编辑

请大家去 http://bugreport.apple.com 并请求弃用。要求它的人越多越好。-retainCount

编辑 #2

作为更新,现在有一个 9223372036854775807。如果你的代码预期是 2,那么你的代码现在已经损坏了。[NSNumber numberWithInt:1]retainCount

评论

1赞 Joe 3/22/2011
retainCount 目前对单例很有用。(现在的问题是单例有多大用处.......- (NSUInteger)retainCount{return NSUIntegerMax;}
8赞 Dave DeLong 3/22/2011
@Joe您可以在不覆盖的情况下创建单例。retainCount
1赞 Joe 3/22/2011
人们也可以烤一个没有鸡蛋的蛋糕。Apple 建议重写 retainCount,以确保单例在非垃圾回收环境中的状态。developer.apple.com/library/mac/documentation/Cocoa/Conceptual/......
5赞 Dave DeLong 3/23/2011
@Joe我知道这一点;谷歌“objective-c单例”,用于所有关于为什么这个例子不是一个很好的例子的讨论。
2赞 Dan Rosenstark 8/12/2012
我使用的一件事是——@DaveDeLong,你可能也会发现这是错误的,但我不这么认为——是覆盖 dealloc 和 inits 并将 NSLogs 放入其中(即使使用 ARC)。这让我对对象是否被分配有一个很好的了解,这是我们通常试图回答的真正问题。
10赞 Egil 5/10/2011 #7

我确实发现 retainCounts 在使用“工具”检查时非常有用。

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

通过配对分配和发布,您可以很好地了解正在发生的事情,并经常解决那些未发布某些内容的困难情况。

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

-1赞 iosdevnyc 3/7/2013 #8

你永远不应该在你的代码中使用它,但它在调试时绝对会有所帮助

0赞 hrchen 5/4/2013 #9

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

4赞 Marc Culler 11/29/2015 #10

当然,切勿在代码中使用 retainCount 方法,因为其值的含义取决于已应用于对象的自动释放次数,而这是无法预测的。但是,它对于调试非常有用 - 特别是当您在调用主事件循环之外的 Appkit 对象的方法的代码中查找内存泄漏时 - 并且不应弃用它。

在你努力表达你的观点时,你严重夸大了价值的不可思议的性质。确实,它并不总是参考计数。有一些特殊值用于标志,例如,用于指示永远不应解除分配对象。像1152921504606846975这样的数字看起来非常神秘,直到你用十六进制写出来并得到0xfffffffffffffff。9223372036854775807是十六进制0x7fffffffffffffff。有人选择使用这样的值作为标志也就不足为奇了,因为假设您每秒将 retainCount 递增 100,000,000 次,则需要将近 3000 年的时间才能获得与较大数字一样高的 retainCount。

-1赞 Peng 6/5/2018 #11

Dave 的帖子中使用的示例是 NSNumber 和 NSStrings...所以,如果你使用其他一些类,比如UIViews,我相信你会得到正确的答案(保留计数取决于实现,这是可以预测的)。