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