iOS 内存管理小记

作者: osbornZ | 来源:发表于2017-02-26 16:50 被阅读54次

iOS内存管理的原理是引用计数,引用计数就是统计一块内存的所有权,当这一内存被创建或者被另一对象或指针指向时候,引用计数会+1; 之后不再持有内存的时候,引用计数-1;当一块内存的引用计数变为0,表示没有任何对象或指针持有这块内存,系统便会释放掉这块内存。

MRC ARC

Objective-C中提供了两种内存管理机制MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),分别对应内存的手动和自动管理。

  • MRC 需要我们自己添加创建和释放的代码,自定义管理内存,谁分配谁释放的原则;
  • ARC 本质其实是MRC,系统编译期在合适的地方帮我们添加了 retain 和 release等代码,减少了代码的同时降低了内存出错的概率;
MRC

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString* str = [[[NSString alloc] initWithString:@"test"] autorelease];
//use str...
[pool release];
//str is released

release autoRelease

release是一个实例方法,只能由对象调用,它的作用是使对象的内存空间的引用计数减1,若引用计数变为0则系统会立刻释放掉这块内存。

autorelease也是一个实例方法,同样只能由对象调用,它的作用于release类似,但不是立刻减1,相当于一个延迟的release,通常用于方法返回值的释放。

那么问题来了,autoRelease对象到底什么时候会被释放 ?

所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中;在一次完整的运行循环结束之前,会被销毁;

关系如此:(线程-RunLoop-AutoRelease Pool-AutoRelease)

autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop;
autoReleasePool 没有单独的结构,autoReleasePoolPage双向链表; 向一个对象发送 - autorelease消息,就是将这个对象加入到当前AutoreleasePoolPage的栈顶next指针指向的位置。

void *context = objc_autoreleasePoolPush();
// {}中的代码
objc_autoreleasePoolPop(context);

AutoRelease Pool

我们知道系统自动释放池会在runloop 迭代结束时释放autorelease 对象,然而为了能够改变其释放时机;pool本质上是一个stack,扔到pool中的对象等价于入栈。我们把需要及时释放掉的代码块放入我们生成的autorelease pool中,结束后清空这个自定义的pool,主动地让pool清空掉来达到及时释放内存的目的。

AutoreleasePool 可以在某些情况下,大幅度降低程序的内存占用(自定义NSOperation内存泄露问题;循环处理中,循环体里面的对象都是临时创建使用的情况etc);

关键字

上次在Property中说,它是ivta+存取方法;
而这些内存管理关键字(strong,weak,assign,retain,copy,mutablecopy)系统是如何来帮我们处理的 留坑

在ARC的项目中,对MRC的文件可以添加编译选项-fno-objc-arc的标识来解决编译问题;

sunnyxx 黑幕背后的Autorelease

相关文章

网友评论

    本文标题:iOS 内存管理小记

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