有没有办法“find神秘的保留”…?
最近我正在修复某人的代码。 有一个大class不会释放。 你必须用5或6个版本才能达到dealloc。
我仔细看了看大class,最终find了需要发布的各种东西。
这让我想到: 只需要一些非常简单的方法来“find”对象上的所有保留对象 。我是对的吗?
那么,有没有一种简单的方法来“find所有的保留”在一个对象上? XCode或乐器中是否有其他人都知道的button?
当你找不到一个神秘的东西时,你会怎么做呢?
因此,在iOS的宇宙中,如果有人知道“显示所有的保留来自这个对象”button – 谢谢!
PS请注意,没有泄漏,这个问题是完全无关的泄漏。 对象只是“完全正确”不会释放。
稍后..
法比奥真正惊人的解决scheme:
法比奥提供了一个惊人的解决这个问题。 用九个字来表示:
-(id)retain { NSLog(@"%@", [NSThread callStackSymbols]); return ([super retain]); }
这在许多情况下是非常有用的,并导致许多其他有用的事情。 法比奥,你可能永远每年为我节省了两个人工周。 谢谢!
顺便说一句,如果你刚刚掌握了这一点,并努力与输出,我看到通常会有许多“UINib instantiateWithOwner:”块。 看起来这些会先来,重要的块将跟随。
只是猜测…但你可能会覆盖自定义类的super方法,并抛出一个很好的NSLog打印调用堆栈。
用Joe的实际代码更新
-(id) retain { NSLog(@"%@", [NSThread callStackSymbols]); return ([super retain]); }
另一个重要的细节是[NSThread callStackSymbols]返回一个NSStrings的NSArray,可以被过滤和用于其他目的。 例如在复杂和dynamic的代码中,检查一个方法是否正确导致另一个方法被触发。
注意:在ARC环境中,您需要首先将-fno-objc-arc
到编译器标志,以允许您覆盖保留并调用super。
仪器可以显示每个 malloc的调用堆栈,释放,并保留您的应用程序中的任何Obj-C对象,无需更改代码 。 它适用于使用ARC的情况,而fabio的解决scheme并非如此。
这对于发现这些神秘的保留是非常有用的,例如,当一个对象在应该的时候不会被释放。
就是这样:
- CMD + I (产品/简介)
- 当乐器popup时select“分配”(不泄漏)
- 你的应用应该运行。
- 做任何事情导致你的奥秘保持发生。
- select左侧面板上的“分配”工具。
- 按CMD + 1或在右侧select带有波形的圆圈。 在右下方的面板中,勾选“logging参考计数”选项。 这很重要,或者只有malloc和frees才会被logging下来。
- 在列表右上方的search框中,键入您的类的名称(例如BCMyObject)。
- 这将过滤“统计”列表,以显示您的class级当前有多less个实例。 #Persistent列显示有多less实例正在运行。
- 点击该行,然后点击类名旁边的小箭头 – >。 你会看到面包屑显示“统计>分配摘要> BCMyobject”
- 这显示了所有类的实例(以及哪些是实时的)。
- select一个实例,再次点击箭头(这次是按地址)
- 现在你会在breadcrumps中看到“Statistics> Allocation Summary> BCMyObject> History:0xADDRESS”。
- 这将列出每一个对象malloc'd保留或释放。
- 现在在“logging参考计数”选项所在的左侧面板中,按下看起来像条形图标的盒子,并按下CMD + 3键 。
- select其中一行,您将看到导致该调用的完整调用堆栈 。
简单! (ISH)
在自定义类“保留”上放置一个断点
您可以在保留上设置符号断点,然后将其设置为自定义类的保留方法。 这里的问题是retain是NSObject
上的一个方法,所以当你放置断点的时候,你将得到所有的objective-c类的select。
在这种情况下,最好使用super来覆盖自定义类的retain方法,所以它不会做任何事情,但是可以在其中放置一个断点。
使用断点操作来logging调用者
要添加断点动作,请双击蓝色标记。 在列表中find断点,然后按下右侧的+button。 然后selectDebugger command
并在此字段中添加GDB命令frame 1
,这将向您显示保留的调用者。 通过这个你冷日志所有保留,他们从哪里来。 当以类似的方式logging发布时,你可以检查什么是额外的版本。
它仍然有点乏味,但这是我能想到的最好的。
仪器及其memory management的东西是你的朋友。 泄漏和僵尸是两个最有价值的工具。 使用它们。
产品 – >configuration文件(或Cmd-I)
不幸的是,由于“对象所有权”的概念是一个编码约定(除非启用垃圾回收),所以很难以程序化的方式确定对象的“拥有”是什么。
堆栈日志通常是有用的(我通常使用几个断点与bt;continue
),但只告诉你叫做保留的function,而不是“更大的图片”(例如,你可能“转让所有权” [ivar2 release]; ivar2 = ivar1; ivar1 = nil;
)。 有时这是一个UIKit泄漏,所以你没有源代码,你真的不得不去挖掘。
如果这不是泄漏,然而,请拨几次,看看它崩溃的地方!
你有没有尝试在Xcode中使用“构build和分析”?
让对象的底部不被释放是非常好的。