在进行讲解内存管理之前先来了解一下内存的基础知识:
1、内存区的划分:
栈区(stack):
①栈区主要存储局部变量以及函数的参数。函数调用的过程其实就是入栈出栈的过程。(先进后出,后进先出)
②栈空间的分配是从高到低分配,从低到高存储。
③管理方式:系统自动进行管理,不需要我们手动管理。
堆区(heap): 经过排序的树形结构,通常是二叉树, 常用来实现优先队列堆的存取,是随意的。由程序员自己进行分配和释放,手动进行管理,堆区的空间相对比较大。
静态区(全局区):
由static修饰的变量是静态变量(全局变量)。 ①变量只初始化一次。②如果不给初值的话,默认0。③静态变量只有程序退出的时候才会被释放。
常量区: 也叫文字常量区,一般存储常量字符串。
代码区: 我们的代码编译成的CPU指令所在区域。
2、内存的静态分配和动态分配
静态分配的内存在栈内存中,由系统分配 系统释放 自由度较低。 动态分配的内存在堆内存中有程序员自己灵活分配 ,需要自己管理内存, 自由度较低。
3、内存管理的常见问题:
①内存泄露 :开辟了了一块内存 ,使用完后没有释放。
②提前释放 :释放了一个还要继续使用的内存。
③释放过度: 对一块内存重复释放 造成程序崩溃。
④野指针:释放完内存之后,没有将指针置空。
4、内存管理方式:
垃圾回收:Garbage Collection:程序员只需要开辟内存空间,不需要⽤用代码显示地释放,系统来判断哪些空间不再被使用,并回收这些内存空间,以便再次分配。整个回收的过程不需要写任何代码,由系统自动完成垃圾回收。Java开发中一直使用的就是垃圾回收技术。
MRC:Manual Reference Count(人工引用计数):内存的开辟和释放都由程序代码进⾏行控制。相对垃圾回收来说,对内存的控制更加灵活,可以在需要释放的时候及时释放,对程序员的要求较高,程序员要熟悉内存管理的机制。
ARC:Auto Reference Count(自动引用计数):iOS
5.0的编译器特性,它允许用户只开辟空间,不用去释放空间。它不是垃圾回收!它的本质
还是MRC,只是编译器帮程序员默认加了释放的代码。
几种内存管理方式的特点:
①垃圾回收:(GC)程序员只负责开辟空间,不负责内存释放,内存释放工作由系统自动完成。在iOS中没有垃圾回收机制,但在MAC
OS中存在垃圾回收。
②在iOS中通过引用计数的形式管理内存,当某一块内存区域的引用计数不为0时,说明有对象在使用这一块内存或者说有对象持有这一块内存,那么这一块内存就不能被系统回收,当某一块内存区域的引用计数为0时,说明这块内存区域没有对象引用,那么系统将这一块内存区域及时回收系统自动调用dealloc方法进行回收内存区域。
③iOS里面内存管理方式是MRC(手动引用计数)和ARC(自动引用计数),对于MRC来说,需要我们程序员自己手动去记录某块内存区域的使用情况(也就是引用计数是几),alloc、retain、copy(mutableCopy)、new可以是引用计数加1,release和autorelease可以使引用计数减1。ARC是iOS5出现的,是编译器的特性,基于静态编译,原理是编译器在他认为合适的地方给你自己进行记录引用计数的增减,不需要我们自己去写retain、release、autorelease这些代码。
5、内存管理原则:
①你创建的对象你可以拥有。(创建对象的方法:alloc、new、copy、mutableCopy)
②不是你创建的对象你也可以拥有,使用retain
③你拥有的对象在不需要的时候,要负责释放(release或autorelease),防止内存泄漏
④如果你没有拥有这个对象(通过便利构造器创建的对象),那么不能对他进行释放,防止过度释放。
内存管理黄金原则:
凡是使⽤用了alloc、new、retain或者copy、mutableCopy让内存的引⽤计数增加了,就需要使⽤release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等。
注意:
dealloc方法是当对象的引用计数为0时由系统自动调用的不需要自己调用。autorelease是在未来的某一时刻引用计数减一 ,向一个对象发送autorelease消息,这个对象何时释放,取决于
autoreleasepool,当pool释放或结束的时候,会向自动释放池内发送过autorelease消息的对象发送release消息让该对象释放。