美文网首页
内存管理

内存管理

作者: maniacRadish | 来源:发表于2016-06-02 18:47 被阅读45次

    1.内存区域

    1>堆和栈的区别

    管理方式:
    对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

    申请大小:
    栈是向低地址扩展的数据结构,是一块连续的内存的区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小。
    堆是向高地址扩展的数据结构,是不连续的内存区域,因为系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存,因此堆获得的空间比较灵活,也比较大。

    碎片问题:
    对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出

    分配方式:
    堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

    分配效率:
    栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

    2> iOS内存区域

    2.1> 栈区
    由编译器自动分配释放,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.
    2.2> 堆区
    一般由程序员分配释放,若程序员不释放,程序结束时由系统回收
    2.3> 全局区(静态区)
    全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量相邻的另一块区域.
    全局区分为未初始化全局区: .bss段 和初始化全局区: data段.
    2.4> 常量区
    常量字符串就是放在常量区
    2.5> 代码区
    存放函数体的二进制代码

    2. 字符串的内存管理
    创建字符串的内存空间 堆 常量区

    3. 你是如何优化内存管理
    1> 使用ARC
    2> 延迟加载 懒加载
    3> 重用 在正确的地方使用reuseIndentifier
    4> 缓存 NSCache 保存计算数据
    5> 处理内存警告 移除对缓存,图片 object 和其他一些可以重创建的 objects 的强引用
    5.1> app delegate 中使用 applicationDidReceiveMemoryWarning: 的方法
    5.2> 自定义 UIViewController 的子类 (subclass) 中覆盖 didReceiveMemoryWarning
    5.3> 在自定义类中注册并接收 UIApplicationDidReceiveMemoryWarningNotification 的通知
    6> 重用大开销对象 NSDateFormatter 和 NSCalendar 懒加载/单例 _formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy”; 设置和创建速度一样慢
    7> 自动释放池 手动添加自动释放池
    8> 是否缓存图片 imageNamed imageWithContentOfFile
    9> 混编

    10> 循环引用 delegate block nstimer
    11> 移除 kvo nsnotificationcenter 并未强引用,只记录内存地址,野指针报错 UIViewController自动移除 一般在dealloc中
    13> performselector 延迟操作 [NSObject cancelPreviousPerformRequestsWithTarget:self]

    4. 循环引用
    delegate属性的内存策略

    block循环引用 实际场景

    5. autorelease的使用
    1> 工厂方法为什么不释放对象
    很多类方法为了在代码块结束时引用的对象不会因无强引用而被释放内存采用自动释放的方式,当其最近的自动释放池释放时该对象才会释放.
    2> ARC下autorelease的使用场景
    ARC中手动添加autoreleasepool可用于提前释放使用自动释放策略的对象,防止大量自动释放的对象堆积造成内存峰值过高.
    3> 自动释放池如何工作
    自动释放池时栈结构,每个线程的runloop运行时都会自动创建自动释放池,程序员可以代码手动创建自动释放池,自动释放的对象会被添加到最近的(栈顶)自动释放池中,系统自动创建的自动释放池在每个运行循环结束时销毁释放池并给池中所有对象发release消息,手动创建释放池在所在代码块结束时销毁释放池并发消息统一release

    避免内存峰值
    SDWebimage中加载gif图片 大循环
    栈结构 栈顶

    统一发release消息
    5> ARC和MRC的混用
    5.1> MRC>ARC
    把MRC的代码转换成ARC的代码,删除内存管理操作(手动)
    xcode提供了自动将MRC转换成ARC的功能,操作菜单栏edit -> Refacotor(重构) -> Convert to Objective-C ARC
    5.2> ARC>MRC
    在ARC项目中继续使用MRC编译的类,在编译选项中标识MRC文件即可"-fno-objc-arc"
    在MRC项目中继续使用ARC编译的类在编译选项中标识MRC文件即可"-fobjc-arc”

    相关文章

      网友评论

          本文标题:内存管理

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