zoukankan      html  css  js  c++  java
  • xcode 之动态Instruments和静态Analyze 调试

    1> 什莫是内存泄露?
    内存泄露指当一个对象或变量在使用完成后没有释放掉, 这个对象一直占用着这部分内存, 直到应用停止.

    2> 这种没有 释放掉的对象 多了会发生什么呢?
    如果这种对象过多,内存就会耗尽,其他应用就无法运行.

    3> 在哪里比较普遍?
    这个问题在 C++, C 和 Objective-C的 MRR 中是比较普遍的问题.

    4> 理论与实际?
    从理论上讲, 内存泄露是由对象或变量没有释放引起的, 但实践证明并非所有的未释放的对象或变量都会导致内存泄露, 这与硬件环境和操作系统系统环境有关。

    5> 我们该怎么办呢?
    我们需要检测工具帮助我们找到这些"泄漏点".

    6> 为什么要测试代码的内存泄露?
    内存的泄露导致我们软件在运行过程中占用越来越多的内存,占有资源却又得不到及时清理,会导致我们程序效率越来越低,反应慢,会影响我们用户体验,失去市场的竞争能力.

    查找内存泄露的方法

    一,Analyze  

    xcode - product - Analyze 即可     或 快捷键:  CMD+shift +b

    先使用 Analyze 静态分析查找可疑泄漏点

    Analyze主要分析以下四种问题:

     1) 逻辑错误:访问空指针或未初始化的变量等;

    2) 内存管理错误:如内存泄漏等;

    3) 声明错误:从未使用过的变量;

    4) Api调用错误:未包含使用的库和框架。

    小结:
    这里使用 Analyze 静态分析查找出来的泄漏点,称之为"可疑泄漏点".之所以称之为"可疑泄漏点",是因为这些点未必一定泄露,确认这些点是否泄露, 还要通过 Instruments 动态分析工具的 Leaks 和 Allocations 跟踪模板. Analyze 静态分析只是一个理论上的预测过程.

    出现以下图片的图标

    二,Instruments的使用 动态监测

    xcode - product - Profile 即可     或 快捷键:  CMD+i

    再用Instruments动态分析中的 Leaks 和 Allocations 跟踪模板进行动态跟踪分析, 确认这些点是否泄漏, 或者是否有新的泄漏点出现等.

    Instruments:它有很多跟踪模块可以动态分析和跟踪内存, CPU 和文件系统.

    在 instruments 中,虽然选择了 Leaks 模板,但默认情况下也会添加 Allocations 模板.基本上凡是内存分析都会使用 Allocations 模板, 它可以监控内存分布情况。

    ① 选中 Allocations 模板,(图1区域),右边的3区域会显示随着时间的变化内存使用的折线图,同时在4区域会显示内存使用的详细信息,以及对象分配情况.

    ② 点击 Leaks 模板(图中2区域), 可以查看内存泄露情况。如果在3区域有 红X 出现, 则有内存泄露, 4区域则会显示泄露的对象.

    打用leaks进行监测:
    点击泄露对象可以在(下图)看到它们的内存地址, 占用字节, 所属框架和响应方法等信息.打开扩展视图, 可以看到右边的跟踪堆栈信息

     

    双击某一个方法,同样会跳转到代码里,会有每一句代码对应的内存分配情况,根据这些信息,可以对程序里不同代码的内存占用情况有一些认识,并进行针对性的优化。

    Call Tree


    然后双击 上文图片中的任意一行,就会跳到代码处内存泄漏的地方(事实上,到这步,很多内存泄漏的问题都会被发现),当然也有一些泄露还是看不出来的.
    第三步
    然后我们选择对ARC调试很有用的一个部分Circles & Roots,通过这个我们可以看到详细的ARC引用计数过程。然后,我们看到如下图

    小的红色矩形点击可以看到引用计数的详细信息(ARC 就是自动引用计数,计数为0,则对象会被释放)

    大的红色矩形可以绘制对象引用环的图,这里如果是我们自己的东西,就能看出来各个对象之间的引用.

     

    Circles & Roots


    如果这里没有引用环的图. 首先我们找一下我们自定义的对象,正常完成任务这个对就应该释放的. 为了确认这个对象有没有释放, 可以重写 dealloc 方法, 在此方法中 log 释放信号, 看看是否被释放.

    如果这里就是没有释放,我们可以点击这儿对象后的箭头详细的看下, 这个对象的引用计数变化如图.

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

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

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

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

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

        -(void)setOperationFinished
        {
         [self.session invalidateAndCancel];
         }

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

    总结:其实大多数问题在双击上文的代码部分就可以解决了,少数问题需要详细的分析ARC引用过程。

    建议
    如果我们未发现表示内存泄露的红 X, 但是我们想进一步评估某个对象对于内存的应用, 可以看看 Allocations 模板的折线图. 反复执行从创建对象 -> 销毁对象 这个过程, 如果总占用内存数会随之增加, 这说明这个对象没有释放, 有些时候虽然占用的内存不是很严重, 但是也会增加占用内存, 因此必须释放这个对象.

    提示:有些情况下, 对象没有释放是无法检测到的,反复测试内存占用也没有明显的增加, 这时最好在配置比较低的设备上测试一下, 如果问题依然, 可以不用释放对象. 但是从编程习惯上讲, 我们应该释放该对象.

    事实上,内存泄露是及其复杂的问题, 工具使用是一方面, 经验是另一方面. 提高经验, 然后借助工具才能解决内存泄露的根本.

    扩展小知识
    1.什莫是内存溢出 out of memory ?
    是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

  • 相关阅读:
    【Codeforces 429D】 Tricky Function
    【HDU 1007】 Quoit Design
    S3C2440开发环境搭建(Ubuntu)
    ubuntu 14.04使用root登陆出现错误“Error found when loading /root/.profile”解决
    Ubuntu 14.04下NFS安装配置
    gcc及其选项详解
    class_create(),class_device_create()创建/dev/xxx 名字
    class_create(),device_create自动创建设备文件结点
    ZedGraph 总论
    ZedGraph类库之基本教程篇
  • 原文地址:https://www.cnblogs.com/liaolijun/p/7883322.html
Copyright © 2011-2022 走看看