解决方法
应用程序的“活动对象图”是可以直接或间接从应用程序中的各种“根”到达的所有分配.一个“根”本身就代表一个对象的实时引用,无论是否有其他显式引用根.
例如,全局变量是根;通过引用对象,通过定义,全局变量将该对象的一部分应用于实时对象图.而且,通过暗示,全局变量引用的对象的任何对象也被认为是活的;不泄漏
堆栈也一样;任何线程的活堆栈引用的任何对象本身都被认为是活的.
考虑到这一点,泄漏和遗弃的记忆实际上有两个不同的含义.
泄漏
一个泄漏是一个内存,它没有引用在应用程序的活动对象图中的任何活动对象的分配.
即内存是无法访问的,因此无法再次被引用(禁止错误).这是死记忆
注意,如果对象A指向对象B,对象B指向A,但是活动对象图中的任何内容都不指向A或B,则仍然是泄漏.如果B> A和A-> B参考文献都是保留参考文献,您将得到一个保留周期&泄漏.
被遗弃的记忆
由于应用程序逻辑问题,应用程序的活动对象图中的分配不再可达,因此被视为已被放弃,但不会泄漏.
例如,假设您有一个缓存,其条目是NSData的实例,这些实例是从URL中包含URL中的会话ID(通用模式)的某个URL下载的,并且该会话ID URL用作查找内容的关键字缓存.现在,说用户注销,导致会话ID被销毁.如果缓存还没有修剪所有特定于该会话ID的条目,则所有这些NSData对象将被放弃,但不会泄漏,因为它们仍然可以通过缓存到达.
在现实中,这两者之间的区别很大,没有什么用处,因为这种修复需要非常不同的策略.
修复泄漏是为了找出额外的保留来自哪里(或者如果基于malloc()的泄漏)可能需要插入空闲()的空闲调用.由于无法从实时对象图中获取检测到的泄漏,因此修复泄漏确实是直接的.
修复遗弃的记忆可能会相当棘手,有几个原因.
首先,从实时对象图可以看到内存.因此,根据定义,在您的应用程序中存在一个保持内存活动的算法问题.寻找和修复通常会更加困难和潜在的破坏性,然后修复一个漏洞.
其次,对被遗弃的分配可能存在不归零的非保留弱引用.也就是说,如果你找出修剪强力参考文献的地方,使分配实际上消失,那并不意味着你的工作已经完成;如果有任何剩余的不归零弱引用,它们现在将悬挂指针和….. BOOM.
正如阿米特所指出的那样,Heapshot Analysis非常擅长发现这两种泄漏,废弃的记忆和相当重要的整体“不良记忆增长”.