最近我正在修复某人的代码。有一个大课堂不会dealloc。你必须使用5或6个版本来获取它才能获得dealloc。
我仔细查看了大班,最终发现了需要发布的各种事情。
这让我想到了:只需要一些非常简单的方法来“找到”对象的所有保留 ..我是对的吗?
那么,是否有一种简单的方法可以“找到对象上的所有保留”? XCode或Instruments中是否有其他人都知道的按钮?
当你找不到这样的谜团时,你会怎么做?
所以在iOS世界中,如果有人知道“显示所有保留来自此对象的位置”按钮 - 谢谢!
P.S。请注意,没有泄漏,这个问题与泄漏完全无关。对象只是“完全正确”不会释放。
稍后..
Fabio为这个问题提供了令人震惊的解决方案。用九个字来说,它是:
-(id)retain
{
NSLog(@"%@", [NSThread callStackSymbols]);
return ([super retain]);
}
这在许多情况下非常有用,并且会带来许多其他有用的东西。法比奥,你可能每年为我节省了两个人工周的工作。谢谢!
顺便说一下,如果你刚刚掌握了这个并且在输出上挣扎,我看到通常会有很多以“UINib instantiateWithOwner:”为特色的块。看起来这些将首先出现,重要的块将会出现。答案 0 :(得分:72)
乐器可以显示每个 malloc的调用堆栈,发布和保留应用中的任何Obj-C对象,无需更改代码。当您使用ARC时,它可以正常工作,而不是来自fabio的解决方案。
找到那些神秘的保留物非常有用 - 例如当一个对象在它应该的时候不会释放。
以下是:
轻松! (ISH)
答案 1 :(得分:22)
猜测......但你可能会覆盖自定义类调用super的retain方法并抛出一个好的NSLog来打印调用堆栈。
-(id) retain {
NSLog(@"%@", [NSThread callStackSymbols]);
return ([super retain]);
}
另一个重要细节是[NSThread callStackSymbols]返回NSStrings的NSArray,可以过滤并用于其他目的。例如,在复杂和动态代码中,检查方法是否正确导致另一个方法触发。
注意:
在ARC环境中,您需要先将-fno-objc-arc
添加到编译器标志,以便覆盖retain和call super。
答案 2 :(得分:5)
您可以在retain上设置符号断点,然后将其设置为自定义类的retain方法。这里的问题是retain是NSObject
上的一个方法,所以在放置断点时你可以选择所有的objective-c类。
在这种情况下,最好通过调用super来覆盖自定义类的retain方法,因此它不会做任何事情,但你可以在其中放置一个断点。
要添加断点操作,请双击蓝色标记。在列表中找到断点,然后按右侧的+按钮。然后选择Debugger command
并在此字段中添加GDB命令frame 1
,这将显示保留的调用方。通过这个你冷却记录所有保留和他们来自哪里。以类似的方式记录版本时,您可以检查什么是额外版本。
这仍然有点乏味,但这是我能想到的最好的。
答案 3 :(得分:1)
乐器及其内存管理的东西是你的朋友。泄漏和僵尸是两种最有价值的工具。使用它们。
产品 - >简介(或Cmd-I)
答案 4 :(得分:1)
遗憾的是,不可能以编程方式确定“拥有”对象的内容,因为“对象所有权”的概念是一种编码约定(除非您启用垃圾收集)。
堆栈日志记录通常很有用(我通常使用一些带有bt;continue
的断点),但这只会告诉你调用retain的函数,而不是“更大的图片”(例如你可能会用{{转移所有权“) 1}})。有时这是一个UIKit泄漏,所以你没有源代码,你真的不得不去挖掘。
如果不是泄漏,请拨打[ivar2 release]; ivar2 = ivar1; ivar1 = nil;
几次,看看它崩溃的位置!
答案 5 :(得分:-1)
您是否尝试在Xcode中使用“Build& Analyze”?
让对象的底部不被释放是很好的。