当前位置:   article > 正文

IOS内存泄漏动静态方法排查_ios 检测内存溢出

ios 检测内存溢出

hi,大家在实际开发中,有没有遇到app异常崩溃,界面delloc方法不调用的问题呢?很可能是由于你的app出现了内存泄漏的问题,今天就和大家从简入深的探讨一下怎样通过简单的分析方法或xcode自带工具instrument的静态分析,动态分析来定位出问题的代码以解决的吧。

先提出两个基本概念:

1,内存溢出(out of memory):是指在运行代码时,程序的内存突然增大,使得没有足够的内存空间去申请,导致程序崩溃的现象。

2,内存泄漏( memory leak) :是指程序在申请内存后,使用完并没有进行释放该处内存空间,一次内存泄漏危害可以忽略,但累计就会造成可用内存减少,直到用光崩溃。

我们时不时在制造内存泄漏,无论是新手开发者还是业界老鸟。它和我们的经验无关。最重要的是要清除它们,让我们的app更干净,避免崩溃。为什么?因为它们很危险。

注:内存应尽可能保持在100M以下,如若长时间超出就很可能崩溃,有一个不全机型崩溃数的统计表供大家参考,如下图:
在这里插入图片描述

简单观察内存

我们在用xcode实时调试代码的过程中,就可以简单的查看运行程序的cpu占用率,内存占用,电池,硬件,网络的信息。我们平常可以在跑项目时,关注下memory这个属性,如果内存突然增大,就意味着这个位置会出现待优化代码。这也是较简单的一种调试方法。
xcode内存占用
但这样的操作,我们并不能很好的查找出出现问题的代码,只能大致的去排查出相应的范围,再去分析查找。那有没有一种办法,可以定位出现问题的代码,让我们快速的解决问题呢!答案肯定是有的。接下来让我们看下xcode自带工具instrument对内存的分析吧。

静态分析

概念

静态代码分析(Static Code Analysis):用来发现源代码潜在的错误与缺陷,源代码编译后只有在运行时有可能会产生细微的错误,他们可能难以识别和修复,所以这些潜在的威胁在开发过程中一定要尽可能清理干净,尽量编写的时候注意类似可能潜在的威胁与缺陷

可排查到的问题

1.逻辑缺陷,如访问未初始化的变量和空指针
2.内存管理的缺陷,如分配后的内存泄漏
3.无效数据(未使用的变量)缺陷
4.使用api缺陷,不遵循库或者框架的使用规则

具体的操作

在Xcode 选项栏里面选择Product -> Analyze (快捷键: command + shift + B) ,点击运行即可。

在这里插入图片描述
运行完毕后就会如上图,点击右上角出现的小标志,就会定位到相应的问题

部分问题及解决

1,Localizability Issue (Apple)
xcode希望字符串需要做本地化处理或者宏定义

解决:在 Build Settings 里面找到 Missing Localizability(缺少本地化) 设置为NO,就会忽略这个问题,或者在应用里进行本地化。

2,Dead store
无效数据: 意思就是有一些属性或者对象初始化了又没被使用

解决:去掉初始化方法,直接赋值

3,Memory error 内存错误
可能在运行过程中出现nil。

解决:通常这种情况下,只需要添加一个非空判断,保证传入的参数不为空即可

以上为我们使用instrument静态分析的部分,但终究是提前预测,实际上出现内存泄漏的位置还没有排查到,所以接下来就引出今天的重要知识点,动态内存泄漏排查!

动态分析

概念

动态代码分析(Dynamic analysis):是在程序实际运行时完成的特定分析。 Thins类型的分析,在运行时完成,可以检测特定行为,如访问释放内存,泄漏内存,在函数中花费的时间等。简而言之,静态分析就是高级编译,动态分析是一种特殊的测试形式,通常需要为您的程序进行“检测”(即在二进制级别进行修改)。

具体的操作

在项目启动后,点击xcode->open developer tool -> instruments进入下图界面

注:本人用的xcode13,不启动运行出现了只显示内存,所以建议启动后,再运行instruments

在这里插入图片描述
instrument中包含了多个模版,协助开发者排查项目,常用的有Timer Profiler(时间探查),Activity Monitor(活动监视器),Network:跟踪 TCP/IP和 UDP/IP 连接等。。。
本文主要讲解下面两个模板:
1,Leaks(泄漏):一般的查看内存使用情况,检查泄漏的内存,并提供了所有活动的分配和泄漏模块的类对象分配统计信息以及内存地址历史记录;
2,Allocations(内存分配):跟踪过程的匿名虚拟内存和堆的对象提供类名和可选保留/释放历史;

双击进入leak可进入下图界面:
在这里插入图片描述
1,工具栏:允许您启动、暂停和停止数据分析、添加仪器、隐藏和显示窗格等。。
2,时间轴窗格:显示为给定跟踪记录的数据的图形摘要。
3,详细信息窗格:显示有关跟踪文档中仪器收集的数据的详细信息。 4,检查器窗格:包含有关当前数据记录和仪器特定扩展详细信息的摘要信息。

点击开始进入记录数据,在某段时间停止,如上图所示。
allocation为内存分配情况统计。
leaks为隔断时间判断下是否有内存泄漏发生。

数据分析

先从上图详细信息窗格左上角的四个状态进行讲解,如下图:
在这里插入图片描述

statistics

全量统计,如图:
在这里插入图片描述
内存相关概念:
1,All Heap Allocation 堆上malloc分配的内存,不包过虚拟内存区域。
2,All Anonymous VM 匿名的虚拟内存区域

该图从左至右含义:
在这里插入图片描述
通过对比一段时间的对象个数,及占用的内存大小分析数据。

allocations list

内存分配列表统计:
在这里插入图片描述

Allocations List提供了一种比较纯粹的方式,让你看到内存的分配的列表,我们一般会选择内存从高到低,看看是不是有什么意外分配的大内存块

generations

标记时间段:可以查看一段时间内内存增加等信息。
在这里插入图片描述

call trees

栈调用统计:也是大家常用的统计方式。
如下图:选中call tree,双击出现红x的部分,查看完整调用信息。
下面依次点击
1,Separator By Thread,按照线程来对内存
2,Invert Call Tree 倒置函数栈
3,Hide System Libraries 隐藏系统库
在这里插入图片描述
snapshots:调试时间间隔
就会出现如下图:
打开调用栈,左面显示人头的就为开发者自己写的代码哦!
点击reveal in xcode会定位到具体出问题的代码!!
在这里插入图片描述

注:调用栈信息不是全都可reveal in xcode,如果无法对应,可通过上图右下角检查器窗格找到对应信息

双击Allocations可进入,启动分析后如下图界面:
在这里插入图片描述
注:虚拟内存是处于进程和物理内存之间的一个中间层,由系统生成,内部作分页管理

可见,是比leak多了一个VM Tracker分析。
VM Tracker是可以帮助你快速查看虚拟内存块的用量状态以及根据虚拟内存块的tag进行分类一种工具。
那从左到右的含义为:
1,% of Res, 当前Type的VM Regions总Resident Size占比。
2,Type,VM Regions的Type,All和Dirty算是统计性质的Type,__TEXT表示代码段的内存映射,__DATA表示数据段的内存映射。MALLOC_TINY,MALLOC_LARGE,CG Image等Type可以从VM Region的Extend Info中读取出来,后面会着重介绍。
3,Regs,当前Type的VM Region总数。
4,Path,VM Region是从哪个文件映射过来,因为有些类似于__DATA和mapped file的内存块是从文件直接映射过来的。
5,Resident Size,使用的物理内存量。
6,Dirty Size,使用中的物理内存块如果不交换到硬盘保存状态就不能复用,那么就是Dirty的内存块,比如你主动malloc出来的内存块,如果不保留其中的状态就把它给别人用,那你肯定就无法恢复这个内存块的信息,所以它是Dirty的。如果是一个映射到内存的文件,就算使用它的内存块,还是可以重新从磁盘载入文件到内存的,所以是非Dirty的,比如最上面图中的mapped file那一行,你可以看到Dirty Size是0。
7,Swapped Size,在OSX中,不活跃的内存页可以被交换到硬盘,这是被交换的大小。在iOS中,只有非Dirty的内存页可以被交换,或者说是被卸载。
8,Virtual Size,VM Regions所占虚拟内存的大小
9,Res. %,Resident Size在Virtual Size中的占比

问题排查定位

经过本人的调试,内存泄漏比较严重的出现在以下几个位置,大家平常开始的时候应多注意。
1,循环应用,也就是说block与self相呼应用,那么解决办法最好的也是weak,strong相互作用,当然还有其他方法,这里不细说,大家可以去查下。
2,delegate强引用,可能出现在代理模式的传递上,所以建议大家都weak调用该属性。
3,观察者模式,不用了一定要销毁哦,ios9之后会出现一定的内存引用。
4,nstimer同样会造成循环引用,要记得用完之后手动销毁nstimer。
5,AFNerworking的AFHttpSessionManager类要用单例调用哦,否则不会销毁,会出现内存引用!

总结

好啦!以上为作者带来的内存泄漏分析。另外,排查定位到系统方法时,不要就放弃在那里了,因为很有可能是自己调用的问题,就像afnetworking的session需要单例调用这类问题!!!记住!一次内存溢出不足为惧,但是累计下来就会占用较多内存,最后导致内存泄漏。所以大家还是尽可能减少内存泄漏的代码哦,哈哈,就这样,如果大家有什么看法可以评论区指证,祝好。

参考:
官网:
https://help.apple.com/instruments/mac/current/#/dev2843b037.
比较好的文章
http://www.cocoachina.com/articles/25383.
https://www.jianshu.com/p/06fb68edf647.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/478194
推荐阅读
相关标签
  

闽ICP备14008679号