61ca78b0fa076f2266ecb950bfb816f6
内存管理面试要点

内存存储区

iOS内存存储区分为栈、堆、全局和静态变量存储区、常量存储区、代码区。
代码区->常量存储区->全局和静态变量存储区->堆->栈在内存中的地址从低往高。
栈的生长方向为向低地址生长,堆的生长方向为向高地址生长。
栈和堆在程序运行时会动态增长,其他区在编译期确定

用来存放局部变量、函数参数等。底层实现数据结构为栈,后申请的变量先释放。

程序通过malloc,new创建出来的对象存放在堆中。

全局、静态变量存储区

全局,静态变量存储在该区。该区在编译期就确定了。

常量存储区

常量存储在该区。该区在编译期就确定了。

代码区

二进制代码存储在该区。该区在编译器就确定了。

引用计数规则

MRC

对象操作 OC中对应的方法 对应的 retainCount 变化|
生成并持有对象 alloc/new/copy/mutableCopy等 +1
持有对象 retain +1
释放对象 release -1
废弃对象 dealloc 0

一、规则
1、四个法则

  • 自己生成的对象,自己持有。
  • 非自己生成的对象,自己也能持有。
  • 不在需要自己持有对象的时候,释放。
  • 非自己持有的对象无需释放。

2、任何以下列名称为前缀的方法,若其返回值为 object,则方法调用者持有该 object:

  • alloc
  • new
  • copy
  • mutableCopy

3、还有一个更为严格的规则:任何以 init 为前缀的方法必须遵守下列规则:

  • 该方法必须是实例方法;
  • 该方法必须返回类型为id或其所属class、superclass、subclass 的对象;
  • 该方法返回的 object 不能是 autorelese,即方法调用者持有返回的 object。

4、『方法调用者持有该 object』也就意味着该 object 的内存问题需要调用方管理。
在此之外的任何方法返回的 object,其调用方都不持有,即返回的应该是 autorelease object。

ARC

ARC 是苹果引入的一种自动内存管理机制,会根据引用计数自动监视对象的生存周期,实现方式是在编译时期自动在已有代码中插入合适的内存管理代码以及在 Runtime 做一些优化。

引用计数实现原理

有两种实现方式
1、在对象内部保持引用计数。
2、在全局表里保持引用计数,key为对象,value为对象的引用计数。
iOS采用的第二种方式,在调用retain方法的时候,在全局表里面查找对象并增加引用计数;调用release方法的时候,在全局表里面查找对象并减少引用计数,如果引用计数为0,释放掉对象,并且从表里面移除该项数据。

weak实现原理

iOS在底层用了一个全局表来实现weak,表的key为引用对象,value为一个数组,代表了所有weak指针。对用weak指针引用对象时,如果不存在那就往weak指针数组里面插入该weak指针。 当weak指针销毁时候,会从weak指针数组里面移除该weak指针。 当引用对象销毁的时候,会自动地把weak指针数组置为nil。
weak跟assign、__unsafe_unretained区别在于引用对象销毁时,weak会自动置为nil,其他的不会,因此用weak不会造成野指针,因此不会崩溃。
assign与__unsafe_unretained差不多,最好不要用assign修饰对象。

Autorelease实现原理

如果对一个对象调用Autorelease,该对象会加入到自动释放池,当自动释放池释放的时候,会对该对象调用release。

_bridge、__bridge_retained、__bridge_transfer

_bridge

_bridge直接转换,不进行任何内存转移操作

__bridge_retained

__bridge_retained 的作用是使得被赋值变量持有赋值 object。
```
ARC如下代码:
id obj = [[NSObjcet alloc] init];

top Created with Sketch.