NSMutableString未在autoreleasepool中列出_CFAutoreleasePoolPrintPools()

问题描述:

使用ARC(XCode 4.3.2,iOS 4.0),_CFAutoreleasePoolPrintPools()不会在任何池中打印地址令牌。我检查了令牌是在游泳池结束后按预期发布的,所以没有问题,但是场景背后有些东西。我怀疑它可能与objc_autoreleaseReturnValue有关。NSMutableString未在autoreleasepool中列出_CFAutoreleasePoolPrintPools()

@autoreleasepool { 
    NSMutableString *token = [NSMutableString string]; 
    // When following line uncommented, 
    // **token** is listed in autorelease pool by _CFAutoreleasePoolPrintPools. 
    //[token appendFormat:@"%@", @"xyz"]; 

    NSLog(@"%@", token); 

} 

那么,是不是_CFAutoreleasePoolPrintPools()可靠吗? 令牌如何自动释放,尽管未在任何自动释放池中列出?

编辑:当我终于找出原因,并确定它已被列出,appendFormat不能工作不同。似乎在调用appendFormat时,内存地址位于([1..F] XXX XXXX)范围内,因此_CFAutoreleasePoolPrintPools会精确地列出这些地址,并且我可以在搜索时找到地址。

我被内存地址中最左边过多的0咬住了。我直接复制并搜索为令牌返回的地址。 NSMutableString实例在_CFAutoreleasePoolPrintPools()返回的列表中实际显示为__NSCFString。

(lldb) po token 
(NSMutableString *) $1 = 0x[-->0<--]898e690 

(lldb) po (NSString *)_CFAutoreleasePoolPrintPools() 
...  
objc[731]: [0x82dc1a8] ################ POOL 0x82dc1a8 
objc[731]: [0x82dc1ac]   0x898e690 __NSCFString 

这是objc_retainAutoreleaseReturnValue的魔力。如果自动释放的对象将被调用者立即保留,则它不会自动释放 - 所以它不会显示在自动释放池中。我调出了程序集助手窗口,在调用[NSMutableString string]调用obj_msgSend之后,查看对objc_retainAutoreleaseReturnValue的调用。

查看this blog post了解更多信息。它引用在Apple code,说评论:

objc_autoreleaseReturnValue()检查主叫方的指示 回国后。如果呼叫者的指令立即呼叫 objc_autoreleaseReturnValue,则被呼叫者省略-autorelease 并将结果保存在线程本地存储中。如果呼叫方不是 看起来像它合作,那么被调用方通常会调用-orautorelease,如 。

objc_autoreleaseReturnValue检查返回值是否与线程本地存储中返回的值相同 。如果是,则直接使用该值 。如果不是,则假定该值是真正的自动释放,并且再次保留 。无论哪种情况,主叫方现在都会保留对该值的引用 。

带标记的指针对象参与快速自动发布 方案,因为它保存了消息发送。在慢速情况下,它们不会被输入到 自动释放池中。

+0

我忘了提及retainCount由objc_retainAutoreleasedReturnValue()增加,并且字符串方法创建字符串后,retainCount为2。我认为[NSMutableString string]返回一个autoreleased字符串,所以objc_retainAutoreleasedReturnValue()保留它。 – lockedscope