当前位置: 首页 > news >正文

自己做传奇网站张家界住房和城乡建设局网站

自己做传奇网站,张家界住房和城乡建设局网站,中小型网站建设公司,wordpress 导航站主题目录 为什么要检测内存泄漏#xff1f;什么是内存泄漏#xff1f;内存泄漏排查方法1. 使用Zombie Objects2. 静态分析3. 动态分析方法定位修改Leaks界面分析Call Tree的四个选项#xff1a; 内存泄漏原因分析1. Leaked Memory#xff1a;应用程序未引用的、不能再次使用或释… 目录 为什么要检测内存泄漏什么是内存泄漏内存泄漏排查方法1. 使用Zombie Objects2. 静态分析3. 动态分析方法定位修改Leaks界面分析Call Tree的四个选项 内存泄漏原因分析1. Leaked Memory应用程序未引用的、不能再次使用或释放的内存。2. Abandoned Memory 内存仍被应用程序所引用没有任何有用的用途。3. Cached Memory内存仍然由应用程序引用可以再次使用以获得更好的性能。 前言 内存溢出out of memory是指程序在申请内存时没有足够的内存空间供其使用出现out of memory。通俗理解就是内存不够通常在运行大型软件或游戏时软件或游戏所需要的内存远远超出了你主机内安装的内存所承受大小就叫内存溢出。内存泄露 memory leak是指程序在申请内存后无法释放已申请的内存空间一次内存泄露危害可以忽略但内存泄露堆积后果很严重无论多少内存迟早会被占光。 为什么要检测内存泄漏 迅速膨胀的内存可以很快让程序毙命所以要多加防范。即使有 ARC自动引用计数内存管理机制但在现实中对象之间引用复杂循环引用导致的内存泄漏仍然难以避免所以关键时刻还要自力更生。分析内存泄露不能把所有的内存泄露查出来有的内存泄露是在运行时用户操作时才产生的。 什么是内存泄漏 内存泄漏指的是一块内存被分配后不再使用但是没有被程序正确释放回系统从而导致该内存继续占用在程序中无法被其它任务使用。 这通常发生在使用了动态内存分配但未及时或正确释放或者由于编程逻辑错误导致。如果不加以管理会导致程序消耗过多的内存甚至导致应用程序崩溃。 比如下MRC中如下代码会造成泄漏 NSString* string [[NSString alloc] init]; ... // [string release]; //ARC下编译器自动添加此代码但由于ARC机制编译器会在适当的时机帮我们加上release代码避免了内存泄漏。不过即使在ARC中也有肯能因对象不释放而引起内存泄漏比如使用CF框架下的对象而没有做CFRelease操作。 虽然string所占的内存很小可以忽略不计但也是有安全隐患的就像前言所述代码中这里泄漏一点内存那里又泄漏一点内存反反复复内存总会有用尽的那一刻。 毕竟系统本身内存有限分配给每个App的内存更加有限当系统内存慢慢不足时我们的App会变得越来越卡顿。 当系统内存告急时App中首先会收到didRecieveWarning提醒如果我们不第一时间采取措施释放内存那么系统就会把我们的App Kill掉所以我们应该重视内存泄漏问题。 didRecieveWarning调用流程看这篇文章【iOS】didReceiveMemoryWarning实例方法 内存泄漏排查方法 1. 使用Zombie Objects 有时候我们会收到EXC_BASD_ACCESS错误提示但没能跳到具体的出错代码行此时可以启用Zombie Objects功能来寻找那些已被释放的对象。 进入edit Scheme 选中僵尸对象选项 按照以上步骤开启Zombies Objects而后Memory查看器变为disable 系统在即将回收对象时如果发现通过环境变量启用了僵尸对象功能那么还将执行一个附加步骤即把对象转化为僵尸对象而不彻底回收。 测试代码 void PrintClassInfo(id obj) {Class cls object_getClass(obj);Class superCls class_getSuperclass(cls);NSLog( %s : %s , class_getName(cls), class_getName(superCls)); }- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.UIView* view [[UIView alloc] init];NSLog(Before release:);PrintClassInfo(view);[view release];NSLog(After release:);PrintClassInfo(view); }2. 静态分析 打开Xcode项目并点击Product-Analyze 静态内存泄漏分析如下 静态分析方法能发现大部分的问题但是只能是静态分析结果有一些并不准确还有一些动态分配内存的情形并没有进行分析。所以仅仅使用静态内存泄漏分析得到的结果并不是非常可靠如果需要我们需要将对项目进行更为完善的内存泄漏分析和排查。那就需要用到我们下面要介绍的动态内存泄漏分析方法Instruments中的Leaks方法进行排查。 3. 动态分析方法 打开Xcode项目点击Product-Profile 选择Leaks这时项目也在模拟器或真机上运行起来了 或者直接在自己的项目中运行程序选中Memory点击右上角的Profile in instruments 都可以进入下面的页面 由于 Leaks 是动态监测所以我们需要手动操作 APP进行测试一边操作 APP一边观察 Leaks 的变化在 暂停按钮 的右边 我们可以选择正在 运行的程序 选择设备 App, 之后点击 红点 Record红色圆圈按钮运行。 观察如果发现在 Leaks 里面有一个 红色X这说明了我们的 APP 存在内存泄露。 就像这样 点击暂停点击其中一个然后我们开始分析。 定位修改 此时选中有红色叉的 Leaks下面有个Leaks 字方格点开选中 Call Tree。 接着就是最关键的一步在这个界面的右下角有若干选框选中Invert Call Tree(从上到下跟踪堆栈信息) 和 Hide System Libraries(表示隐藏系统的函数) 在详情面板选中显示的若干条中的一条双击会自动跳到内存泄露代码处然后点击右上角 Xcode 图标进行修改。 Leaks界面分析 Leaks 启动后会开始录制随着对模拟器运行的 App 的操作可以在 Leaks 中查看内存占用的情况。 Leaks顶部分为两栏Allocations 和 Leaks右侧的曲线代表内存分配和内存泄漏曲线。 Call Tree的四个选项 Separate By Thread: 线程分离,只有这样才能在调用路径中能够清晰看到占用CPU最大的线程.每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU的重线程按线程分开做分析这样更容易揪出那些吃资源的问题线程。特别是对于主线程它要处理和渲染所有的接口数据一旦受到阻塞程序必然卡顿或停止响应。Invert Call Tree: 从上到下跟踪堆栈信息.这个选项可以快捷的看到方法调用路径最深方法占用CPU耗时这意味着你看到的表中的方法,将已从第0帧开始取样,这通常你是想要的,只有这样你才能看到CPU中话费时间最深的方法,比如FuncA{FunB{FunC}},勾选后堆栈以C-B-A把调用层级最深的C显示最外面.反向输出调用树。把调用层级最深的方法显示在最上面更容易找到最耗时的操作。表示隐藏系统的函数调用这个就更有用了,勾选后耗时调用路径只会显示app耗时的代码,性能分析普遍我们都比较关系自己代码的耗时而不是系统的.基本是必选项.注意有些代码耗时也会纳入系统层级可以进行勾选前后前后对执行路径进行比对会非常有用.因为通常你只关心cpu花在自己代码上的时间不是系统上的隐藏系统库文件。过滤掉各种系统调用只显示自己的代码调用。隐藏缺失符号。如果 dSYM 文件或其他系统架构缺失列表中会出现很多奇怪的十六进制的数值用此选项把这些干扰元素屏蔽掉让列表回归清爽。递归函数, 每个堆栈跟踪一个条目拼合递归。将同一递归函数产生的多条堆栈因为递归函数会调用自己合并为一条。 内存泄漏原因分析 在目前主要以ARC进行内存管理的开发模式导致内存泄漏的根本原因是代码总存在循环引用从而导致一些内存无法释放这就会导致dealloc方法无法被调用。 开启了ARC并不是就不会存在内存问题苹果有句名言ARC is only for NSObject。 使用ARC的项目一般内存泄漏都是 malloc、自定义结构、资源引起的多注意这些地方进行分析。 注如果你的项目使用了ARC随着你的操作不断开启或关闭视图内存可能持续上升但这不一定表示存在内存泄漏ARC释放的时机是不固定的。 引起内存泄漏的几种原因 1. Leaked Memory应用程序未引用的、不能再次使用或释放的内存。 在OC的ARC机制下使用CF或CG对象时忘记手动调用CFRelease或CGRelease。 CGImageRef* imageRef CGImageCreateWithImageInRect(someImage, someRect); // ... // CGImageRelease(imageRef); // 释放内存for循环中超多次加载比较占内存的对象频繁创建大量占用内存的对象如果不使用autorelease会导致内存无法及时释放。 for (int i 0; i 1000; i) {autoreleasepool {UIImage* image [UIImage imageNamed: largeImage];// ...} }2. Abandoned Memory 内存仍被应用程序所引用没有任何有用的用途。 大多是OC对象、block、timer、delegate等循环引用问题造成引用计数一直不为零。 OC对象循环引用 interface Person : NSObject property (nonatomic, strong)Person* friends; endimplementation Person - (void)dealloc {NSLog(Person 对象被释放); } endint main(int argc, const char * argv[]) {autoreleasepool {Person* person1 [[Person alloc] init];Person* person2 [[Person alloc] init];person1.friends person2;person2.friends person1;}return 0; }person1和person2互相引用形成了循环(强)引用这两个对象的引用计数不会降为0dealloc方法并没有被执行。 解决办法就是使用弱引用打破循环property (nonatomic, weak)Person* friends。 - Block循环引用 interface MyClass : NSObject property (nonatomic, strong) void (^myBlock)(void); - (void)setupBlock; endimplementation MyClass- (void)setupBlock {// __weak typeof(self) weakSelf self;self.myBlock ^{// __strong typeof(weakSelf) strongSelf weakSelf;NSLog(%, self); // 造成强引用循环// if (strongSelf) {// NSLog(%, strongSelf);// }}; }endMyClass *obj [[MyClass alloc] init]; [obj setupBlock];如果没有注释掉的那段代码self.myBlock对self产生了强引用导致self的引用计数永远不会为零从而引起循环引用。 Timer循环引用 interface MyClass : NSObject property (nonatomic, strong) NSTimer *timer; endimplementation MyClass - (void)startTimer {// __weak typeof(self) weakSelf self;self.timer [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:selector(timerFired) userInfo:nil repeats:YES]; }- (void)timerFired {// Timer fired actions } end如果没有注释掉的那段代码NSTimer对self保持强引用target: self增加了ViewController的引用计数如果不进行[timer invalidate];就别想调用dealloc了而self对NSTimer也保持强引用形成循环引用。 timer属性也最好设置为弱引用weak。 Delegate引起的循环引用 interface MyObject : NSObject property (nonatomic, strong)idMyDelegate delegate; endinterface MyViewController : UIViewController MyDelegate property (nonatomic, strong) MyObject *myObject; endimplementation MyViewController - (void)viewDidLoad {[super viewDidLoad];self.myObject.delegate self; } end与Timer同理myObject对delegate使用强引用delegate又对myObject保持强引用形成循环引用。 解决方案是使用弱引用property (nonatomic, weak)idMyDelegate delegate;。 ViewController的子视图对self的持有 我们有时候需要在子视图或者某个cell中点击跳转等操作需要在子视图或cell中持有当前的ViewController对象这样跳转之后的back键才能直接返回该页面同时也不销毁当前ViewController。此时你就要注意在子视图或者cell中对当前页面的持有对象不能是强引用尽量assign或者weak否则会造成循环引用内存无法释放。 3. Cached Memory内存仍然由应用程序引用可以再次使用以获得更好的性能。 为了快速访问而存储起来的对象。 以缓存图片提高性能为例 class UIImage; interface ImageCache : NSObject property (nonatomic, strong) NSMutableDictionary* cache;(instancetype)sharedInstance; - (UIImage *)imageForKey:(NSString *)key; - (void)setImage:(UIImage *)image forKey:(NSString *)key; end// ImageCache.m #import ImageCache.h #import UIKit/UIImage.himplementation ImageCache (nonnull instancetype)sharedInstance {static ImageCache *sharedInstance nil;static dispatch_once_t onceToken;dispatch_once(onceToken, ^{sharedInstance [[self alloc] init];sharedInstance.cache [NSMutableDictionary dictionary];});return sharedInstance; }- (void)setImage:(nonnull UIImage *)image forKey:(nonnull NSString *)key {self.cache[key] image; }- (nonnull UIImage *)imageForKey:(nonnull NSString *)key {return self.cache[key]; }end// 使用缓存 UIImage* image [UIImage imageNamed: example.png]; [[ImageCache sharedInstance] setImage: image forKey: example];// 之后访问缓存的图片 UIImage* cachedImage [[ImageCache sharedInstance] imageForKey: example]; 示例中图片被缓存以便快速访问从而提高性能。缓存图片使用的内存不是泄漏因为这戏内存是有意保留以供将来使用的。
http://www.dnsts.com.cn/news/119932.html

相关文章:

  • 创新的商城网站建设如何注册一个网站域名备案
  • 高师本科化学实验教学体系建设与创新型人才培养 教学成果奖申报网站慈溪网站建设网站推广
  • 网站新闻被百度收录网站建设课程的感受
  • thinkphp5网站开发公司网站发布流程
  • 网站上的高清图怎么做php网站后台教程
  • 请人做网站注意事项wordpress编辑器自定义按钮
  • 汕头网站建设网站自己制作图片文字图片
  • 常州做网站软件深圳百度网站排名优化
  • 做网站用啥语言WordPress网站hym地图
  • 网站建设信息科技公司潍坊中企动力做的网站怎么样
  • 做网站的步骤视频网站开发涉及到哪些知识产权
  • 苏州网站设计师招聘信息网站建设有哪些困难
  • 做设计的素材网站网站除了做流量还需要什么软件
  • 建站系统wordpress下载生活中的网页设计作品
  • 个人网站的建设参考文献高端网站定制北京
  • 网站建设推广加盟百度seo关键词排名推荐
  • 穷游 网站开发苏州网站制作公司
  • 网站建设与维护 国赛建设网站你认为需要注意哪些问题
  • 网站网站开发设计推广收款码平台有哪些
  • 泉州网站建设科技公司志丹网站建设
  • 高端网站推广企业把网站关闭原因
  • 北京网站制作报价《两学一做 榜样》网站
  • 国家电网网站开发图片素材php企业网站源码
  • 初期网站开发费会计分录和别人做网站接单赚钱
  • 石家庄网站系统开发网站开发维护合同样板
  • 举报不良网站信息怎么做php做网站多少钱
  • 网站开发制作计算器ajax数据库网页网站设计
  • 做线上交互的网站网站页面打不开
  • 江苏建设工程招投标网站响应式博客网站模板
  • 护肤品网站建设方案多媒体应用设计师怎么报考