有没有办法“找到神秘的保留”......?

时间:2011-04-07 20:52:54

标签: iphone memory-management xcode4 retain

最近我正在修复某人的代码。有一个大课堂不会dealloc。你必须使用5或6个版本来获取它才能获得dealloc。

我仔细查看了大班,最终发现了需要发布的各种事情。

这让我想到了:只需要一些非常简单的方法来“找到”对象的所有保留 ..我是对的吗?

那么,是否有一种简单的方法可以“找到对象上的所有保留”? XCode或Instruments中是否有其他人都知道的按钮?

当你找不到这样的谜团时,你会怎么做?

所以在iOS世界中,如果有人知道“显示所有保留来自此对象的位置”按钮 - 谢谢!

P.S。请注意,没有泄漏,这个问题与泄漏完全无关。对象只是“完全正确”不会释放。


稍后..

法比奥真正令人震惊的解决方案:

Fabio为这个问题提供了令人震惊的解决方案。用九个字来说,它是:

-(id)retain
    {
    NSLog(@"%@", [NSThread callStackSymbols]);
    return ([super retain]);
    }

这在许多情况下非常有用,并且会带来许多其他有用的东西。法比奥,你可能每年为我节省了两个人工周的工作。谢谢!

顺便说一下,如果你刚刚掌握了这个并且在输出上挣扎,我看到通常会有很多以“UINib instantiateWithOwner:”为特色的块。看起来这些将首先出现,重要的块将会出现。

6 个答案:

答案 0 :(得分:72)

乐器可以显示每个 malloc的调用堆栈,发布和保留应用中的任何Obj-C对象,无需更改代码。当您使用ARC时,它可以正常工作,而不是来自fabio的解决方案。

找到那些神秘的保留物非常有用 - 例如当一个对象在它应该的时候不会释放。

以下是:

  • CMD + I (产品/简介)
  • 弹出乐器时选择“分配”(非泄漏)
  • 你的应用应该运行。
  • 做任何导致你的神秘事件发生的事情。
  • 选择左侧面板上的“分配”工具。
  • CMD + 1 或选择右侧带有wave的圆圈。在右下方的面板中,勾选“记录参考计数”选项。这很重要,或者只记录mallocs和frees。
  • 在列表右上角的搜索框中,键入类的名称(例如BCMyObject)。
  • 这会过滤“统计信息”列表,以显示您的班级当前有多少实例。 #Persistent列显示有多少实例。
  • 点击该行,然后点击小箭头 - >在班级名称旁边。你会看到面包屑显示'统计>分配摘要> BCMyobject'
  • 这将显示所述课程的所有实例(以及哪些实例)。
  • 选择一个实例,然后再次点击箭头(这次按地址分类)
  • 现在你会看到'统计>分配摘要> BCMyObject>历史:在breadcrumps中的0xADDRESS。
  • 每次保留或释放对象malloc时,都会列出此列表。
  • 现在在“记录参考计数”选项的左侧面板中,按下看起来像带有框的栏的图标或按 CMD + 3
  • 选择其中一行,您会看到导致通话的完整调用堆栈

轻松! (ISH)

答案 1 :(得分:22)

猜测......但你可能会覆盖自定义类调用super的retain方法并抛出一个好的NSLog来打印调用堆栈。


使用Joe

中的实际代码进行更新
-(id) retain {
NSLog(@"%@", [NSThread callStackSymbols]);
return ([super retain]);
}

另一个重要细节是[NSThread callStackSymbols]返回NSStrings的NSArray,可以过滤并用于其他目的。例如,在复杂和动态代码中,检查方法是否正确导致另一个方法触发。

注意: 在ARC环境中,您需要先将-fno-objc-arc添加到编译器标志,以便覆盖retain和call super。

答案 2 :(得分:5)

在自定义类'retain

上放置一个断点

您可以在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”?

让对象的底部不被释放是很好的。