NSM 可变数据。为啥保留计数 1 比我预期的要高?

Posted

技术标签:

【中文标题】NSM 可变数据。为啥保留计数 1 比我预期的要高?【英文标题】:NSMutabledata. Why is the retain count 1 higher that I would have expected?NSM 可变数据。为什么保留计数 1 比我预期的要高? 【发布时间】:2009-10-17 20:13:20 【问题描述】:

我正在尝试每天使用牙线,锻炼身体,并确保在保留和释放之间保持平衡。

这让我感到困惑。我有一个 ivar:

NSMutabledata *_alignmentData 

以及与之关联的综合属性:

// .h file
@property (nonatomic, retain) NSMutableData *alignmentData;

// .m file
@synthesize alignmentData=_alignmentData;

我开始从服务器异步拉取数据:

self.connection = 
[[[NSURLConnection alloc] initWithRequest:theRequest delegate:self] autorelease];

并在分配数据缓冲区后立即在异步回调中使用:

// This prints 0. Cool.
NSLog(@"BEFORE [_alignmentData retainCount] = %d", [_alignmentData retainCount]);

// Create a place to receive the data that will arrive asynchronously:
self.alignmentData = [NSMutableData data];

// This prints 2. Shouldn't this be 1 ?!?
NSLog(@" AFTER [_alignmentData retainCount] = %d", [_alignmentData retainCount]);

为了使在上述 self.alignmentData 分配后触发的第一个异步回调中的问题复杂化,我再次检查了保留计数:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 

    // This prints 1. 
    NSLog(@"[_alignmentData retainCount] = %d", [_alignmentData retainCount]);
    [self.alignmentData setLength:0];


所以,保留计数似乎从 0 上升到 2,然后下降到 1。有人可以向我解释这是怎么可能的吗?

注意:有人告诉我不要使用保留计数作为调试辅助工具,但这在诸如 Objective-C 之类的非垃圾收集语言中根本不实用。

【问题讨论】:

【参考方案1】:

不使用保留计数作为调试辅助是切实可行的。事实上,经验丰富的 Objective-C 编码人员会告诉你不要注意保留计数。担心他们的人通常是 Objective-C 的新手,他们最终会像你一样感到困惑。

您不必担心保留计数。某些东西比您预期的保留更多的事实不一定与您的代码有任何关系,也不一定表明存在错误,确定是哪种情况的唯一方法是使用适当的调试工具,就像您被建议的那样首先做。

在这种特殊情况下,2 是该对象在该时间点的正确保留计数,因为它是使用保留计数 1 创建的,然后由您的 setter 方法保留。

【讨论】:

是的,是的,查克。我知道我在平衡我的保留/释放方面很清楚。我不漏。 Clang说我可以走了。我现在正式发誓不再为保留计数而烦恼。承诺。感谢您 - 实际上相当严厉 - 警告。 对不起,如果听起来过于严厉。那真的不是我的本意。我一直在寻求清晰而不是看我的语气,因为我认识一些人花了很多时间担心保留计数,这真的只是浪费时间,所以我想帮助人们尽早而不是迟到.【参考方案2】:

来自Memory Management Programming Guide:

保留计数

通常没有理由明确询问对象的保留计数是多少(请参阅retainCount)。结果通常具有误导性,因为您可能不知道哪些框架对象保留了您感兴趣的对象。在调试内存管理问题时,您应该只关心确保您的代码遵守所有权规则。

我从未遇到过查询对象的retainCount 很有用的情况。如果你遵循正确的内存管理规则,你会没事的。

至于您的实际问题,自动发布不会立即发生。每当当前的自动释放池恰好被弹出时,它们就会发生。由于您没有明确管理任何自动释放池,因此您无法控制自动释放何时发生。但是,由于您似乎遵循了正确的内存管理规则,因此您无需担心。

【讨论】:

【参考方案3】:

可能是因为您正在分配计数为 +1 和自动释放的对象,然后它被设置为一个属性,该属性调用它的保留,所以 +2,原始对象是自动释放的,所以它下降到+1。

【讨论】:

这是正确答案,[NSData data] 返回一个自动释放的对象。 小精灵,啊哈!我开始怀疑这一点。 Autorelease 是 retainCount 暂时上升的隐藏原因。非常感谢。

以上是关于NSM 可变数据。为啥保留计数 1 比我预期的要高?的主要内容,如果未能解决你的问题,请参考以下文章

类型安全连接与 Spark 数据集的安全性比我预期的要低

为什么 Dapper 的批量插入比我预期的要慢很多?

为啥 fwrite 写的比我告诉它的要多?

boost::this_thread::sleep_for 的睡眠时间比我预期的要长得多。

为啥 <INPUT> 比我说的要宽?

为啥在 C# .NET 中写入 Excel 范围所需的时间比预期的要长得多?