我有一个用Swift写的iOS应用程序泄漏内存 - 在某些情况下应该释放一些对象,但事实并非如此。我通过简单地添加deinit
这样的调试消息来了解这个问题:
deinit {
println("DEINIT: KeysProvider released")
}
因此,在应该导致对象释放的此类事件之后,deinit消息应该出现在控制台中。但是,对于应该释放的某些对象,消息将丢失。仍然,Leaks Developer Tool没有显示任何泄漏。我该如何解决这种情况?
答案 0 :(得分:106)
在Xcode 8中,您可以单击调试工具栏中的“调试内存图”按钮(显示在屏幕底部):
只需在左侧面板中标识您认为应该已取消分配的对象,它将显示对象图(显示在上面的主画布中)。这对于快速识别在相关对象上建立强引用的位置非常有用。从这里,你可以开始你的研究,诊断为什么那些强引用没有被解决(例如,如果有问题的对象有一个应该已经解除分配的其他东西的强引用,也可以查看该对象的图表,你可能会发现问题(例如强参考周期,重复计时器等)。
注意,在右侧面板中,我看到了调用树。我通过打开方案设置中的“malloc stack”记录选项来获得它:
无论如何,完成后,可以单击上面第一个屏幕快照右侧面板中堆栈跟踪中显示的相关方法调用旁边的箭头,您可以看到最初建立强引用的位置:
上述记忆诊断技术(及更多)在WWDC 2016 Visual Debugging with Xcode的后半部分进行了演示。
传统的仪器技术(在使用旧版Xcode时特别有用)在我的原始答案中描述如下。
我建议使用Instruments的“Allocations”工具和“Record Reference Counts”功能:
然后,您可以在Instruments中运行该应用程序,然后搜索您知道正在泄漏的课程,并通过单击箭头进行钻取:
然后,您可以使用右侧的“扩展详细信息”面板深入查看详细信息并查看堆栈跟踪:
在“扩展详细信息”面板中,将焦点放在黑色代码而不是灰色系统调用上。无论如何,从“扩展详细信息”面板,您可以在Instruments ::
中深入查看源代码
有关使用Instruments跟踪内存问题的更多信息和演示,请参阅:
答案 1 :(得分:2)
使用仪器检查由于保留但未泄漏的内存导致的泄漏和内存丢失。后者是未使用的内存,仍然指向。在仪器上的分配工具中使用标记生成(快照)。
如何使用“快照”查找内存褶皱,请参阅:bbum blog
基本上,该方法是运行Instruments分配工具,获取快照,运行代码的迭代并重复另外3到4次快照。这将指示在迭代期间分配但未释放的内存。
要弄清楚披露的结果,以查看个别分配。
如果您需要查看对象使用仪器的保留,释放和自动释放的位置:
在仪器中运行,在分配中设置"记录参考计数" on(对于Xcode 5及更低版本,您必须停止录制以设置选项)。导致应用程序运行,停止录制,向下钻取,您将能够看到所有保留,发布和自动释放的位置。