iOS内存管理

使用CADisplayLink、NSTimer有什么注意点?

  • 注意内存泄漏、循环引用的问题(self弱引用timer会造成内存泄漏,强引用timer会造成循环引用)
  • 使用NSProxy作为timertarget,然后弱引用self,打破循环引用的问题
  • NSProxy效率比NSObject高,专门用来做消息转发的,会省略以下步骤:
    1. 去父类寻找方法(本来NSProxy自身也没其他方法了)
    2. 动态方法解析阶段
    3. 消息转发的第一步forwardingTargetForSelector
  • 最后直接来到消息转发的第二步,执行methodSignatureForSelector有返回值再执行forwardInvocation

介绍下内存的几大区域讲一下

  • 低地址
  • 保留:其他用途,大小由平台决定(32位、64位)
  • 代码段(__TEXT):编译之后的代码,例如函数
  • 数据段(__DATA):常量区,比如全局变量、静态变量
  • 字符串常量:例如 NSString *str = @"123";(直接写出来的,不是通过方法创建的那种字符串)
  • 已初始化数据:例如 static int a = 10;(定义就赋值的)
  • 未初始化数据:例如 static int b;(没赋值的)
  • heap:通过allocmalloccalloc等动态分配的空间(实例对象),分配的内存空间地址【越来越大】
  • stack:函数调用开销,比如局部变量,分配的内存空间地址【越来越小】(先进后出)
  • 内核区:系统内核相关的区域,只能系统访问,例如让线程休眠的操作
  • 高地址
iOS程序的内存布局.jpg

你对 iOS 内存管理的理解

  • 使用引用计数来管理OC对象的内存
  • 一个新创建的OC对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间
  • 调用retain会让OC对象的引用计数+1,调用release会让OC对象的引用计数-1
  • 内存管理的经验总结:
  • 当调用allocnewcopymutableCopy方法返回了一个对象,在不需要这个对象时,要调用release或者autorelease来释放它
  • 想拥有某个对象,就让它的引用计数+1;不想再拥有某个对象,就让它的引用计数-1
引用计数和weak引用的存储.jpg

ARC 都帮我们做了什么?

  • ARCLLVM编译器Runtime系统相互协助的一个结果
    - LLVM:例如在某个作用域的{}即将结束的时候,自动对里面的对象调用release方法
    - Runtime:例如weak指针的实现,在程序运行的过程中,监控到对象要销毁时会去清空对象的弱引用

weak指针的实现原理

  • weak指针会将弱引用存储到一个哈希表(SideTable->weak_table)里面,当对象要销毁时取出这个哈希表,把里面存储的弱引用都清除掉
  • 对象调用dealloc时会判断isaweakly_referenced是否被弱引用过,有的话会调用clearDeallocating函数,根据当前对象的地址值通过哈希查找,找到对应的弱引用表,清除里面存储的弱引用
copy和mutableCopy.jpg

autorelease对象在什么时机会被调用release

  • 如果是自定义的autoreleasepool,会在自动释放池的{}结束前一刻调用release
  • 如果不是在自定义的autoreleasepool,而是在main函数的autoreleasepool,是由RunLoop控制的,可能是在某次RunLoop循环中,在RunLoop休眠之前调用了releasekCFRunLoopBeforeWaiting
autorelease时机(验证).jpg
autorelease时机(原理).jpg
AutoreleasePoolPage的结构.jpg
dealloc的底层实现流程.jpg

方法里有局部对象, 出了方法后会立即释放吗

  • MRC环境下不会,会等RunLoop那次循环的休眠之前才释放
  • ARC环境下会,LLVM会在方法的{}即将结束的时候,自动对里面的对象调用release方法

你可能感兴趣的:(iOS内存管理)