美文网首页
iOS开发之进阶篇(14)—— 查找内存泄漏

iOS开发之进阶篇(14)—— 查找内存泄漏

作者: 看影成痴 | 来源:发表于2020-08-25 15:47 被阅读0次
Waterfall.png

内存泄漏

内存泄漏指程序中动态分配的内存由于某种原因未释放或无法释放, 造成系统内存的浪费.
比如MRC中如下代码会造成泄漏:

NSString *string = [[NSString alloc] init];
...
// [string release];  // ARC下, 编译器自动添加此代码

但由于ARC机制, 编译器会在适当的时机帮我们加上release代码, 避免了内存泄漏. 不过即使在ARC中也有肯能因对象不释放而引起内存泄漏, 比如使用CF框架下的对象而没有做CFRelease操作.
例子中, 虽然string所占的内存很小可以忽略不计, 但不得不承认这是有安全隐患的. 假如代码中这里泄漏点内存, 那里又泄漏一点, 反反复复, 内存总会有用尽的那一刻. 毕竟系统本身内存有限, 分配给每个App的内存更加有限. 当系统内存慢慢不足时, 我们的App会变得越来越卡顿. 当系统内存告急时, App中首先会收到didReceiveMemoryWarning提醒, 如果我们不第一时间采取措施释放内存, 那么系统就会把我们的App kill掉. 所以, 我们应该重视内存泄漏问题.

引起内存泄漏的几种原因:

  • Leaked memory: 应用程序未引用的、不能再次使用或释放的内存。
    如ARC下, 使用非OC对象忘记release. 比如CF, CG开头的对象等. 又或者在for循环中超多次加载比较占内存的对象(解决办法是加@autoreleasepool).
  • Abandoned memory: 内存仍然被您的应用程序引用,没有任何有用的用途。
    循环引用. 包括OC对象、block、timer、delegate等循环引用问题, 造成引用计数不为零, 无法回收内存.
  • Cached memory: 内存仍然由您的应用程序引用,可以再次使用,以获得更好的性能。
    为了快速访问而存储起来的对象. 比如存储某个等待界面或者使用单例等.

内存泄漏和内存溢出

内存泄漏指已经废弃的内存没能被系统回收, 造成浪费.
内存溢出指App申请新内存时系统无法提供足够的内存.

内存泄漏最终会导致内存溢出, 但不一定是只有内存泄漏才会引起内存溢出, 有时候可能是因为我们操作不当引起的. 比如同时加载多个大型资源(比如图片/视频等), 或者同时做一些复杂计算(比如做一些图像处理/地图处理等), 都有可能引起内存溢出.

接下来我们讨论查找内存泄漏的几种办法.

1. 使能Zombie Objects

有时候我们会收到EXC_BAD_ACCESS错误提示, 但没能跳到具体的出错代码行, 此时可以启用Zombie Objects功能, 来寻找那些已经被释放的对象.

Zombie Objects 1.png Zombie Objects 2.png

当然, 这方法不一定凑效, 在我印象中没解决过什么问题. 🐶

PS: 开启Zombie Objects, Memory查看器变为disable:

memory_disable.png

2. 静态分析

测试代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    char *bytes = CFAllocatorAllocate(CFAllocatorGetDefault(), 6, 0);
    strcpy(bytes, "hello");
    CFStringRef str = CFStringCreateWithCStringNoCopy(NULL, bytes, kCFStringEncodingMacRoman, NULL);
}

静态分析:

Analyze1.png Analyze2.png

这种方法在前期检测有一定作用, 但也有可能存在误判, 这要我们点击到相应代码行去分析.

3. Leaks工具

测试代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timeIsUp) userInfo:nil repeats:YES];
}


- (void)timeIsUp {
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"111" ofType:@"png"];
    UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
    CGImageRef temImg = image.CGImage;
    // 截图
    temImg = CGImageCreateWithImageInRect(temImg, CGRectMake(0, 0, 100, 100));
    // 释放
//    CGImageRelease(temImg);
}

打开Leaks测试工具:

Leaks1.png Leaks2.png

选择查看函数调用树:

Leaks3.png

调用列表比较复杂, 我们选择隐藏系统的一些方法:

Leaks4.png

开始运行, 无泄漏打V, 有泄漏打X:

Leaks5.png

找到出错函数, 点击可跳转到对应代码行:

Leaks6.png

4. 腾讯MLeaksFinder

https://github.com/Tencent/MLeaksFinder

相关文章

  • iOS开发之进阶篇(14)—— 查找内存泄漏

    内存泄漏 内存泄漏指程序中动态分配的内存由于某种原因未释放或无法释放, 造成系统内存的浪费.比如MRC中如下代码会...

  • iOS 内存泄漏三两事

    iOS 内存泄漏三两事 iOS 内存泄漏三两事

  • instruments - leaks

    iOS开发中,难免会出现内存泄漏的情况,此处通过instruments 中的 leaks工具来检测程序的内存泄漏问...

  • Instruments 之 Memory

    在 iOS 开发中,内存泄漏的检测基本是 APP 功能开发完成之后的必做项目。内存泄漏的检测手段很多,这里就讲讲如...

  • iOS内存分析-工具篇

    之前APP占用太大内存,查找i内存泄露、内存消耗过大 查找泄漏在xcode自带两种内存泄漏查询工具1> Analy...

  • iOS内存泄漏

    iOS开发中,内存泄漏的问题常常遇到. 轻则影响性能,重则导致crash.那么,有哪些方法可以有效的检测内存泄漏的...

  • 【IOS开发进阶系列】Instruments使用专题

    1 工具使用 1.1 Leaks查找泄漏点步骤 使用Xcode和Instruments调试解决iOS内存泄露 ht...

  • iOS 调试神器Instruments——查找内存泄漏

    iOS 调试神器Instruments查找内存泄漏 在日常的开发中总会不经意的留下一些小问题,这些小问题在写的时候...

  • 如何做内存优化?

    为什么要做内存优化?内存优化从内存泄漏开始做起! 据我所知很多iOS开发者都不在意内存泄漏,为什么不在意?因为他们...

  • iOS 内存泄漏的查找

    更多内容请挪步我的博客 前言 最近为[伯乐在线]翻译一篇文章(该文章尚未发布),作者 Russ Bishop 谈到...

网友评论

      本文标题:iOS开发之进阶篇(14)—— 查找内存泄漏

      本文链接:https://www.haomeiwen.com/subject/xdivjktx.html