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

Fat*_*tie 34 iphone memory-management retain xcode4

最近我修了某人的代码.有一个大课堂不会dealloc.您必须使用5或6个版本来获取它以获得dealloc.

我仔细查看了大班,最终找到了需要发布的各种东西.

这让我想到:只需要一些非常简单的方法来"找到"物体上的所有保留物.我是对的吗?

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

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

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

PS注意没有泄漏,这个问题与泄漏完全无关.对象简单地"完全正确"不会释放.


后来......

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

法比奥为这个问题提供了令人震惊的解决方案.九个字,这里是:

-(id)retain
    {
    NSLog(@"%@", [NSThread callStackSymbols]);
    return ([super retain]);
    }
Run Code Online (Sandbox Code Playgroud)

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

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

Ben*_*ton 72

Instruments可以显示每个 malloc 的调用堆栈,发布和保留应用程序中的任何Obj-C对象,无需更改代码.它在您使用ARC时有效,而fabio的解决方案则不然.

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

这是如何做:

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

简单!(ISH)

  • 是的,这是正确的答案.覆盖"保留"也是一种解决方案(尽管可能有点"hacky"),但它不适用于ARC.而这个工具工具 - 确实如此. (3认同)

Fab*_*bio 22

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


使用Joe的实际代码进行更新

-(id) retain {
NSLog(@"%@", [NSThread callStackSymbols]);
return ([super retain]);
}
Run Code Online (Sandbox Code Playgroud)

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

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


Gor*_*tch 5

在自定义类'retain上放置一个断点

您可以在retain上设置符号断点,然后将其设置为自定义类的retain方法.这里的问题是retain是一个方法,NSObject所以你可以在放置断点时选择所有objective-c类.

在这种情况下,最好通过调用super来覆盖自定义类的retain方法,因此它不会执行任何操作,但您可以在其中放置断点.

使用断点操作记录调用者

要添加断点操作,请双击蓝色标记.在列表中找到断点,然后按右侧的+按钮.然后在此字段中选择Debugger command并添加GDB命令frame 1,该命令将显示保留的调用方.通过这个你冷却记录所有保留和他们来自哪里.以类似的方式记录版本时,您可以检查什么是额外版本.

它仍然有点乏味,但这是我能想到的最好的.