如何判断对象是否在NSAutoreleasePool中

Sam*_*Sam 8 memory-leaks objective-c nsautoreleasepool ios retaincount

我想知道一个对象被自动释放了多少次.我已经使用了足够长的目标c,通常可以直接知道某个对象是否已经自动释放,但是我经常会看到处理内存和保留计数的问题.在某些时候,答案总是结束,"你不能相信一个对象的retainCount" - 我同意这一点,但如果你能确定一个对象被自动释放的次数,那么你真的可以信任 retainCount如果你添加了像这样的类别:

@interface NSObject (NSObject_MemoryDebugging)
- (NSUInteger) autoReleaseCount;
- (NSUInteger) retainCountWithAutoRelease;
@end

@implementation]
/** Determine how many times this object has been marked for autorelease **/
- (NSUInteger) autoReleaseCount;
{
   // ??? not sure how to figure this out.
   return 0;
}

 - (NSUInteger) retainCountWithAutoRelease
{
   NSUInteger retainCount = [self retainCount];
   NSUInteger autoReleaseCount = [self getAutoReleaseCount];  // ???
   return retainCount - autoReleaseCount;
}
@end
Run Code Online (Sandbox Code Playgroud)

对于不可变类型仍然存在异常,因为这些通常会在复制期间增加保留计数,因此您仍然无法信任retainCount.

我不建议的

我不是在生产代码中使用retainCount来寻求此答案.但是,我可以看到这对于调试内存问题的人来说很有价值.

我想有些人会讨厌这个问题,因为程序员不应该关心对象被自动释放的次数.编码应该是关于平衡分配,保留,复制,新版本和故事结束.然而,重点是帮助人们敲打头脑. [NSObject retainCount]烧了很多人,这个问题的答案会很酷.

我确定有一种方法可以确定一个对象被自动释放的次数.我只是不知道它是什么,因此问题.

看到类似的问题:Objective-c中NSAutoreleasePool内的对象.

编辑


谢谢大家的答案.你可能会发现这个有趣的=> Ariel指出GNUStep的Cocoa实现,特别是它的NSAutoReleasePool有这个方法:+(NSUInteger)autoreleaseCountForObject:(id)anObject.此方法很慢,只返回调用者线程上NSAutoReleasePools的自动释放计数.还是......有趣的是它在那里.文档引用它实际上只对调试有用.这实际上是我希望在Cocoa框架中以某种方式找到(或找到可能).

我同意答案,即使有可能获得自动释放计数,存在更好的工具(僵尸,泄漏,静态分析器).

and*_*n22 7

首先,您必须处理多个自动释放池和一个多次自动释放的对象,可能在多个池中.

其次,这不是(仅仅)NSAutoreleasePool那是-retainCount不值得信任的.问题在于各种各样的物品,无论是你的还是苹果的,都会出于各种原因而保留物品,这是你们最不为人知的.即使考虑自动释放,您的对象通常也没有您期望的保留计数,因为在幕后,有些东西正在观察它或暂时将它放在字典中等等.

调试内存问题的最佳方法是Leaks仪器,NSZombie和静态分析器.

  • Apple在`-retainCount`的文档中提到了它.除了自动释放之外,他们还提到"这种方法在调试内存管理问题时通常没有价值.因为任何数量的框架对象都可能保留了一个对象以便保存对它的引用......"这就是问题:如此多的目标-C使用Cocoa框架,你不知道Cocoa会对你的对象做什么,更不用说它在保留/释放方面了.并不是说'-retainCount`是不准确的,而是它给出的准确值是没有价值的,因为我们无法理解*为什么*. (2认同)

小智 5

不,没有公共API来确定对象是否已被自动释放.

即使这是公开的,您的-retainCountWithAutoRelease方法也会遇到一些问题:

  • 一个对象可以在同一个自动释放池中多次放置,因此您需要一个自动释放池的自动释放计数,而不是一个标志,指示对象是否已被自动释放;

  • 由于多线程,对象可以放在多个自动释放池中,因此您需要跨越多个自动释放池的自动释放计数;

  • 由于多线程,您需要将代码与Cocoa对保留计数和自动释放池的处理同步,并且Cocoa使用的内部锁定对应用程序不可见.