查找内存泄漏
泄漏分析模板使用"Allocations and Leaks"工具来测量应用程序中的一般内存使用情况,并检查已分配给不再被引用和可访问的对象的泄漏内存。
注意
如果仪器可以访问有关您应用程序源代码的信息,那么泄漏将被报告为一个类名称。 否则,会将泄漏报告为内存地址,例如Malloc- size 。 为确保仪器能够访问有关代码的信息,请从Xcode启动分析(请参阅Xcode中的配置文件 )或配置符号映射文件(请参阅将数据映射到源代码 )。
寻找内存泄漏
-
Launch Instruments。
-
在出现的分析模板选择对话框中,单击“泄漏”。
-
从目标设备和进程列表中选择您的设备和应用程序。
-
单击选择以创建跟踪文档。
-
单击录制按钮(
image:../Art/inline_record_button_2x.png
)(或按Command-R)开始录制。
-
正常使用你的应用程序
-
在时间轴窗格中观察泄漏仪表是否有泄漏。 泄漏出现为红色条。
-
单击时间轴窗格中的泄漏仪器,以在详细信息窗格中显示泄漏相关信息。
从详细信息窗格的导航栏中的详细信息类型列表中选择“调用树”。
-
显示与任何检测到的泄漏相关的方法调用列表。
-
按Command-2显示检查器窗格的显示设置区域。
-
在“呼叫树”显示设置下,选择“反转呼叫树”和“隐藏系统库”。
-
在调用树中,选择要调查的方法调用。
-
按Command-3在检查器的扩展详细信息区域中显示所选方法调用的堆栈跟踪。
-
双击堆栈跟踪中的方法调用以在“仪器”中显示其代码。
-
点击Xcode按钮(
)在详细信息窗格顶部打开Xcode中的代码进行审阅和编辑。
使用回溯调查泄露的对象
-
单击时间轴窗格中的泄漏仪器,以在详细信息窗格中显示泄漏相关信息。
-
从详细信息窗格的导航栏中的详细信息类型列表中选择泄漏。
-
显示通过回溯的泄漏对象的列表。
-
通过Backtrace视图的泄漏将所有泄漏的块通过其分配点聚合,因为源代码中的单个错误可能会导致多次运行时泄漏,因为重复执行代码。
-
选择要调查的对象。
-
点击焦点箭头(
)旁边的对象的内存地址,以便在详细信息窗格中显示对象的内存历史,以及相应的引用计数和方法调用。
-
按Command-3在检查器的扩展详细信息区域中显示所选对象的堆栈跟踪。
-
单击折叠按钮(
)在扩展的详细信息区域中隐藏堆栈跟踪中的系统调用。 这样可以更轻松地找到应用程序的方法。
-
双击堆栈跟踪中的方法以在“仪器”中显示其代码。
-
点击Xcode按钮(
)在详细信息窗格顶部打开Xcode中的代码进行审阅和编辑。
-
打开Xcode以查看创建泄漏的代码后,泄漏的原因可能还不清楚。 Leaks仪器允许您通过使用细节窗格中的循环和根选项查看创建泄漏的循环。
使用循环和根调查泄露的对象
-
单击时间轴窗格中的泄漏仪器,以在详细信息窗格中显示泄漏相关信息。
-
从细节窗格的导航栏中的详细类型列表中选择循环和根。
-
显示按循环显示的泄漏对象的列表。
-
选择要调查的对象。
-
如果可用,查看对象的对象图。
-
点击焦点箭头(
)旁边显示对象的详细信息窗格中的内存历史,以及相应的引用计数和方法调用。
-
按Command-3在检查器的扩展详细信息区域中显示所选对象的堆栈跟踪。
-
单击折叠按钮(
)在扩展的详细信息区域中隐藏堆栈跟踪中的系统调用。 这样可以更轻松地找到应用程序的方法。
-
双击堆栈跟踪中的方法以在“仪器”中显示其代码。
-
点击Xcode按钮(
)在详细信息窗格顶部打开Xcode中的代码进行审阅和编辑。
注意
对于使用自动引用计数(ARC)的应用程序,泄漏对象的对象图视图有助于保留周期的诊断。 通常,解决这些问题的方法是在对象图中使用weak
关键字来标记上位参考。
使用调用树调查泄漏
-
单击时间轴窗格中的泄漏仪器,以在详细信息窗格中显示泄漏相关信息。
-
从详细信息窗格的导航栏中的详细信息类型列表中选择“调用树”。
-
显示与任何检测到的泄漏相关的方法调用列表。
-
按Command-2显示检查器窗格中的显示设置区域。
-
在“呼叫树”显示设置下,选择“反转呼叫树”和“隐藏系统库”。
-
首先显示最近的方法调用。 它还有助于缩小方法调用列表,使其由应用程序调用。 您的应用程序进行的方法调用是黑色的,并且前面有一个用户代码图标(
)
-
选择要调查的方法调用。
-
按Command-3在检查器的扩展详细信息区域中显示所选方法调用的堆栈跟踪。
-
双击堆栈跟踪中的方法调用以在“仪器”中显示其代码。
-
点击Xcode按钮(
)在详细信息窗格顶部打开Xcode中的代码进行审阅和编辑。
虽然仪器可以帮助您检测内存泄漏,但您仍然需要仔细查看相关的内存历史记录和代码,以便识别和解决问题。 以下情况是常见的泄漏原因:
-
1.当对象不再被引用时,在没有相应释放调用的对象上调用了保留。
-
2.使用不会导致对象自动释放的API来分配和初始化一个对象。
-
3.如果一个泄漏不是一个对象,你可能会调用一个API来承担
malloc
内存块的所有权,而你缺少一个对应的free()
调用。
网友评论