Instrument调试内存泄漏-leaks

原创Blog,转载请注明出处

blog.csdn.net/hello_hwc

欢迎关注我的iOS SDK详解专栏

blog.csdn.net/column/manage.html?alias=huangwenchen-ios-sdk



前言:计划是7月份更新Instrument以及调试相关的博客,不过今天刚好遇到个内存泄漏的问题。五月份的数据持久化部分还有三篇左右没更新,六月份集中在多线程开发上。所以这里就简单写一下Instrument中leaks使用吧。


如何打开Leaks

XCode - Open Development Tool - Instruments



打开后会看到很多工具



选择 leaks打开

  1. Allocations纪录了内存分配,用来优化内存使用的
  2. Leaks用来分析内存泄漏。ARC中引起的内存泄漏原因就是饮用环。


然后我们运行下一个小工程,这个工程是接下来要更新的一个异步网络下载tableview图片的前期雏形。

这里要提到的是,我的博客写了这么多篇了,还是没有涉及到好的开源库,这部分后续我会写的。毕竟实际开发的过程中对开源库的选择也很重要,而且会大大提高效率。但是,我希望的是先把基础掌握好,这决定了理解的深度。

内存泄漏的工程下载

看下效果图

乍一看还不错啊,tableview非常流畅,图片能够惰性下载(cell屏幕上再下载),这也是我想要的雏形。可是,好奇的用leaks分析一下

我擦



然后,我们打开leaks,看看错误出现在哪

先选择Leaks和Leaks by Backtrace.这里可以看到那些对象内存泄漏了,泄漏了多少,这个就是简单看看,没有太多调试意义。



然后我们选择对ARC调试很有用的一个部分Circles & Roots

点击Leaks图标可以选择

然后,我们看到如图

  • 小的红圈点击可以看到饮用计数的详细信息(ARC 就是自动饮用计数,计数为0,则对象会被释放)
  • 大的红圈可以绘制对象饮用环的图,不过这里我们很不幸,没有直观的绘图出来。

然后,首先我们找一下我们自定义的对象,发现了DownloadImageOperation这个对象,这个对象是继承自NSOperation,正常在任务完成后就应该释放的。看来没有释放。为了确认,在DownloadImageOperation最后加上log代码,看看是否被释放

-(void)dealloc{
    NSLog(@"dealloc");
}

再运行下程序,果然没有被释放,这里肯定有问题。



点击类似上图的小红圈中的剪头,详细的看下,这个对象的引用计数变化如图

这里

  • All 表示所有的引用计数变化
  • Unpaired表示那些为成对的变化(成对就是leaks识别出了对应的+1,-1)
  • By Group会把相关的变化分成一组,ByTime会按照顺序列出饮用计数变化



我们选择Unpaired 和 ByGroup,看到如图

按照顺序看(最左边的标号)

  • 4 这里,饮用计数是一,这是正确的,因为到这里正常就是应该是OperationQueue保存一个Operation的引用。

    于是,我们把正常的划掉

  • 再继续看,download start 标号6和8是对应的,继续排除问题出现在这里(当然问题不可能出现在这里,这是系统的API,一定会释放,就是简单教大家如何看)



再看看,+1的还剩下标号7 和 11,7 是正常的为Operation分配线程,应当会+1,而11就是我们的问题所在了(大部分Delegate都不会使引用+1)。

我们再看下文档

@property(readonly, retain) id< NSURLSessionDelegate > delegate

原来这个代理是retain啊,不是assign或者weak。所以形成了这样的引用环。

那么怎么办呢?有问题下看文档,我们看到图片中引起饮用计数加一的是

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id<NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue:

看下文档,发现了这个地方

于是,我们要手动的去断开强引用,于是,我们手动去断开

-(void)setOperationFinished{
    [self.session invalidateAndCancel];
    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];

    executing = NO;
    finished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];

}

再运行下看看,能够正常的Dealloc了

2015-06-05 10:28:36.814 AsyncImageTableviewDemo[1245:83664] dealloc
2015-06-05 10:28:36.954 AsyncImageTableviewDemo[1245:83664] dealloc

用leaks分析,也没有内存泄漏了



另外,有注意到的同学可能会问了,我代码里的block直接调用self,不会引起饮用环吗

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    BOOL successed = self.image == nil?NO:YES;
    dispatch_async(dispatch_get_main_queue(), ^(void) {
        self.finishBlock(successed,error,self.image);
    });
    [self setOperationFinished];
    return;
}

这是不会的,因为block有饮用self,但是self并没有饮用block,并不是所有的block都要的

    __weak typeof(self) weakSelf = self;

时间: 2024-10-03 22:29:03

Instrument调试内存泄漏-leaks的相关文章

VC下调试内存泄漏的办法

VC的控制台程序不会跟踪内存泄漏,如果需要调试控制台程序的内存情况,需要_CrtSetDbgFlag 详细原理我也不太懂,我也是从网上摘过来的,直接帖代码 // 内存泄漏跟踪 #ifdef WIN32 #include <SDKDDKVer.h> #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #define VC_MemLeakCheck() _CrtSet

C/C++应用程序内存泄漏检查统计方案

一.前绪 C/C++程序给某些程序员的几大印象之一就是内存自己管理容易泄漏容易崩,笔者曾经在一个产品中使用C语言开发维护部分模块,只要产品有内存泄漏和崩溃的问题,就被甩锅“我的程序是C#开发的内存都是托管的,C++那边也没有内存(庇护其好友),肯定是C这边的问题”(话说一个十几年的程序员还停留在语言层面不觉得有点low吗),笔者毕业不到一年,听到此语心里一万头草泥马奔腾而过,默默地修改了程序,注意不是修改bug(哈哈),而是把所有malloc和free都替换成了自定义宏MALLOC和FREE,d

xcode里面使用Memory Leaks和Instruments检测内存泄漏

教程截图: Leaks和Instruments教程[检测内存泄露]" src="http://pic002.cnblogs.com/images/2011/283130/2011080816513182.jpg"> 作为一名无证程序员,无论你多么精通Objective-C的内存管理,随着时间的推移,你也不可避免的犯内存相关的错误.但通常因为代码量太大,以至于你不可能一行一行的去排除(等你解决完,你设计的动车早相撞了!) 幸运的是,苹果已经提供了一些好的方式来帮助你找到应

_CrtSetBreakAlloc简单内存泄漏检测方法,解决Detected memory leaks!问题

我的环境是: XP SP2 . VS2003 最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} normal block at 0x05785AD0, 152 bytes long. Data: << N N x 7 > 3C AC 4E 10 00 00 00 00 BC A4 4E 10 78 B6 37 00 Object dump complete.   而且每次退出都是一样的.

简单内存泄漏检测方法 解决 Detected memory leaks! 问题

最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} normal block at 0x05785AD0, 152 bytes long. Data: << N N x 7 > 3C AC 4E 10 00 00 00 00 BC A4 4E 10 78 B6 37 00 Object dump complete.   而且每次退出都是一样的.泄漏的内存块都是98500. 解决方法: 1.

Android内存泄漏分析及调试

尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/13017999 此文承接我的另一篇文章:Android进程的内存管理分析 首先了解一下dalvik的Garbage Collection: 如上图所示,GC会选择一些它了解还存活的对象作为内存遍历的根节点(GC Roots),比方说thread stack中的变量,JNI中的全局变量,zygote中的对象(class loader加载)等,然后开始对heap进行遍历.到最后,

(转载)IOS- Instruments使用之使用Leaks检测内存泄漏

转载 :http://www.zhimengzhe.com/IOSkaifa/255950.html 上一篇文章我介绍了Instruments的工具分类和基本使用方法,今天我再来给大家说说Leaks的使用方法. 在早期的iOS开发中,并没有ARC模式,只有MRC模式,必须由开发人员自己管理内存,过程非常繁琐而且容易造成内存泄漏,如今的iOS开发虽然基本都是用的ARC模式,但是有些情况下还是需要我们自己来管理内存,稍有不慎,就可能造成内存泄漏,所以,使用一款内存泄漏的检测工具还是非常有必要的. 接

用Xcode6的Leaks检测内存泄漏

用xcode打开项目之后,选择Product - Profile: 在弹出的窗口中选择Leaks: 然后在设备解锁的情况下,选择Leaks再点击左上角的红色按钮开始运行APP: 红色的柱子表示有内存泄漏,点击Leaks右边田字图片然后选择Call Tree, 选中Invert Call Tree 和Hide System Libraries: 双击这些方法,就会跳转到内存泄露的具体代码:

一次Java内存泄漏调试的有趣经历

人人都会犯错,但一些错误是如此的荒谬,我想不通怎么会有人犯这种错误.更没想到的是,这种事竟发生在了我们身上.当然,这种东西只有事后才能发现真相.接下来,我将讲述一系列最近在我们一个应用上犯过的这种错误.最有意思的是,一开始的迹象揭示的问题,与实际发生的问题完全不同. 在一个凄凉的午夜 午夜刚过,我就被一条来自监控系统的警报吵醒了.Adventory,我们的 PPC (以点击次数收费)广告系统中一个负责索引广告的应用,很明显连续重启了好几次.在云端的环境里,实例的重启是很正常的,也不会触发报警,但