我仍然试图理解我在一个项目中发现的这段代码,我正在研究那个创建它的人离开公司之前我可以问的问题。
这是代码:
-(void)releaseMySelf{
for (int i=myRetainCount; i>1; i--) {
[self release];
}
[self autorelease];
}
据我所知,在Objective-C内存管理模型中,第一条规则是分配另一个对象的对象也负责在将来释放它。这就是我不理解这段代码含义的原因。有什么意义吗?
作者试图解决不了解内存管理问题。他假定一个对象的保留计数会因每次保留而增加,因此尝试通过调用该数量的版本来减少它。可能他没有实施“也有责任在将来发布它”。你理解的一部分。
阅读Apple's memory management concepts。
第一个链接包含来自Apple的引用
retainCount方法不考虑发送给接收方的任何挂起的自动释放消息。
重要说明:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能保留了一个对象以保存对它的引用,而同时自动释放池可能在对象上保留任意数量的延迟版本,所以您不太可能从此获取有用信息方法。要了解必须遵守的内存管理的基本规则,请阅读“内存管理规则”。要诊断内存管理问题,请使用合适的工具:LLVM / Clang Static分析器通常可以在运行程序之前发现内存管理问题。 Instruments应用程序中的Object Alloc仪器(参见仪器用户指南)可以跟踪对象分配和销毁。 Shark(参见Shark用户指南)还描述了内存分配(在程序的许多其他方面)。
由于所有答案似乎都错误地将myRetainCount误读为[self retainCount],让我提供一个原因,为什么可以编写此代码:可能是这个代码以某种方式产生线程或者让客户端注册它,并且myRetainCount实际上是这些客户端的数量与实际操作系统保留计数分开。但是,每个客户端也可能获得自己的ObjC样式保留。
因此,在请求中止的情况下可能会调用此函数,并且可以立即处理所有客户端,然后执行所有版本。这不是一个好的设计,但如果这就是代码的工作方式,(并且你没有遗漏一个int myRetainCount = [self retainCount],或者保留/释放的覆盖),至少它不一定是错误的。
然而,这很可能是责任分配不当,或者是在没有真正改进任何事情的情况下避免保留圈子的狡猾和陈词滥调。
这是一个强制释放内存的肮脏黑客:如果你的程序的其余部分写得正确,你就不需要做这样的事情了。通常情况下,您的保留和释放是平衡的,因此您永远不需要查看保留计数。这段代码所说的是“我不知道是谁保留了我,忘了释放,我只是希望我的记忆得到释放;我不在乎其他参考文献从现在开始就会悬空”。这不会用ARC编译(奇怪的是,切换到ARC可能只是修复了作者试图解决的错误)。
代码的含义是强制对象现在解除分配,无论未来的后果如何。 (会有后果!)
代码存在致命缺陷,因为它没有考虑到其他人实际上“拥有”该对象的事实。换句话说,“分配”该对象的东西,以及任何数量的其他东西可能“保留”该对象(可能是像NSArray这样的数据结构,可能是自动释放池,也许是堆栈帧上的一些代码,只是“保留” );所有这些东西在这个对象中共享所有权。如果对象自杀(这就是releaseMySelf所做的那样),这些“所有者”突然指向不良记忆,这将导致意外行为。
希望这样写的代码会崩溃。也许原作者通过泄漏其他地方的记忆来避免这些崩溃。