OC内存管理模型

OC三种内存管理模式

1.       MRC: ManualRetain-Release手动持有释放,OC本身的引用计数alloc/new/copy/mutablecopy release/autorelease

2.       ARC: Automatic Reference Counting 自动引用计数:

XcodeProjectSetting中,设置Objective-C AutomaticReference CountingYES; Xcode 4.2+,新的Project默认为ARC

3.       GC:GarbageCollection 垃圾回收,MAC-OS支持,IOS不支持。

内存管理问题

没有:未初始化或释放后再使用;不对:赋值和转换后使用越界和释放导致的问题;超出:越界;溢出。

释放:不该释放释放了,该释放没有释放(严格对应,多层结构的隐性内存泄露, 构造函数和虚析构函数,函数返回值,释放的时机)

IOS要从所有权和对象图的整体角度思考。

创建时候拥有所有权: ios中对于内存管理是基于对象所有权来维护的通过alloc ,new, copy,mutableCopy开头创建的对象,那么这个对象就是拥有所有权。

手动管理:创建或拷贝(alloc,new,copy,mutablecopy)后引用计数加1, 然后Retain拥有所有权引用计数加1release引用计数减1autoRelease引用计数推迟减1, 直到引用计数为0,则NSObjectpool管理类会调用dealloc释放对象

误区纠正1dealloc不会使得引用计数从10

误区纠正2:没有调用创建拷贝或者retain函数,只是用指针指向它,那么引用计数不用加1.

OC的内存管理,归根结底要记住一条黄金法则:谁创建谁释放,谁retain谁释放

当等于0时候系统就会调用dealloc释放,不可以自己调用dealloc记住要在dealloc中调用[super dealoc]

 

实例:

(1)简单表现:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSObject *o = [[NSObject alloc]init];    //retainCount为1

[o retain];    //retainCount为2

[o release]; //retainCount为1

[o autorelease]; //retainCount为1

[pool release]; //retaincount为0,触发dealloc方法

 

(2)类实例作为数据成员:

比如ClassA类的一个属性对象的Setter方法:

- ( void )setMyArray:(NSMutableArray *)newArray {

     if (myArray != newArray) {

         [myArray release]; // 先release

         myArray = [newArray retain]; // 后赋值,并调用retain

     }

}

假设这个类的一个实例为'a',调用setMyArray后,我们就可以说a拥有了一个新的myArray实例,也可以说a引用了一个新的myArray实例。其中调用的retain方法,使myArray的retainCount加一,我们需要注意以下两个地方:
setMyarray方法中,在retain之前先release了旧实例一次
(3)类的析构函数中,设置nil不用再release了:

在本实例的dealloc方法中,本应该是要再次release当前实例的,但回头看看参考内存管理准则。它并不合理,对吧。。。多了一次release。这里比较推荐的做法是:
[ myArray setMyArray:nil ];
这样可以巧妙的使当前实例release而不出错(我们可以向nil发送消息?其实它本身就是个整数0),并符合我们的内存管理准则。更主要的是,很简单,你不需要考虑过多的事情。

当等于0时候系统就会调用dealloc释放,不可以自己调用dealloc记住要在dealloc中调用[super dealoc]

 

 

(4)强弱引用:

另外一个比较容易忽略而又比较经典的问题是实例变量的循环引用,Objective-C为此区分了,其实也相当相当的简单:
1
,强引用,上面讲的就是强引用,存在retainCount加一。
2,弱引用,但凡是assign声明并直接用指针赋值实现的被称之为弱引用,不存在retainCount加一的情况。

(5)AutoRelease延迟对象释放:

OC提供了autorelease方法,就是提供了半自动的内存管理,将对象的release数目N动态维护,autoReleasePool调用release时,管理的对象会调用Nrelease,对象的引用计数为0时候,对象才会被销毁,达到延迟销毁的目的。

(0)定义:

NSAutoreleasePool *pool = [[NSAutoreleasePoolalloc] init];

NSObject *o = [[NSObject alloc] init];

//pool实例dealloc时,release一次此实例,重要的是并不是在此行去release

[o autorelease]; 

//此时还可以看到我们的o实例还是可用的,并且retainCount1

NSLog(@ "oretainCount:%d" ,[oretainCount]); 

//pool retainCount0,自动调用其dealloc方法,我们之前备案的小o也将在这里release一次

[pool release];

 

(1)    程序启动的时候会有一个默认的autoReleasePool

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

int retVal = UIApplicationMain(argc, argv, nil, nil);

[pool release];

 

(2)    多个Pool情况下,只有栈顶(最后定义的)pool才起作用。

NSAutoreleasePool *pool1 = [[NSAutoreleasePoolalloc] init];

NSAutoreleasePool*pool2 = [[NSAutoreleasePool alloc] init];

NSAutoreleasePool*pool3 = [[NSAutoreleasePool alloc] init];

NSObject *o = [[NSObject alloc] init]autorelease];

[pool3 release];

[pool2 release];

[pool1 release];

 

自动内存管理ARC

XcodeProject Setting中,设置Objective-C Automatic Reference CountingYES; Xcode 4.2+,新的Project默认为ARC

ARC优点:

不用写retain/release/autorelease这样的代码,甚至连dealloc方法都不需要(前提是类不需要管理C指针)

更好的性能,ARC智能地在”适当“的地方插入retain/release

Block justwork

Less code,less bug

少浪费脑细胞和脑时钟周期。

 

ARC实现的前提:

为了实现ARCLLVM编译器必须保证4条规则

1.不能调用或实现跟引用计数相关的方法(retain/release/autorelease/retaincount等),否则产生编译错误

2.C的结构体里面,不能有Object指针;如果必须使用,那么可以用Objective-C的类代替

3.编译器必须清楚void*是否被retained。引入新的API来转换Objective-CCore Foundation类型的对象

4.编译器必须清楚自动释放的对象,因此AutoreleasePool不能是对象,而只是语义上的符号。@autoreleasepool directive甚至可能在MRC中使用。

 

MRCARC总结:

笔者其实觉得MRC很容易掌握,profile的工具也容易掌握。但ARC实实在在的从安全、可维护性、代码量、性能上有全面的提升。所以除非维护旧的代码,笔者都建议使用ARC。不用担心app依赖第三方的MRC代码,可以通过编译器设置文件的编译属性来混合使用ARCMRC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《操作系统原理》实验指导书 实验一 生产者-消费者模型模拟进程调度 一、实验任务 1、在WINDOWS 2000环境下,创建一个控制台进程,此进程包括4个线程:2个生产者线程和2个消费者线程。 2、用信号量机制解决进程(线程)的同步与互斥问题。 二、实验目的 1.掌握基本的同步互斥算法,理解生产者和消费者模型。 2.了解Windows 2000/XP中多线程的并发执行机制,线程间的同步和互斥。 3.学习使用Windows 2000/XP中基本的同步对象,掌握相应的API。 三、实验要求 1.生产者消费者对缓冲区进行互斥操作。 2.缓冲区大小为10,缓冲区满则不允许生产者生产数据,缓冲区空则不允许消费者消费数据。 3.生产者消费者各循环操作50次。 四、设计思路和采取的方案 1.利用windows提供的API函数CreateSemaphore()创建信号量对象; CreateThread()创建线程; WaitForSingleObject()执行P操作; ReleaseSemaphore()执行V操作; WaitForMultipleObjects()主进程等待线程的结束等函数进行设计。 2.在Windows中,常见的同步对象有:信号量(Semaphore)、互斥量(Mutex) 。 使用这些对象都分为三个步骤,一是创建或者初始化; 接着请求该同步对象,随即进入临界区,这一步对应于互斥量的上锁;最后释放该同步对象,这对应于互斥量的解锁。这些同步对象在主进程中创建,在其子线程中都可。 实验二 存储管理 一、目的和要求 1. 实验目的 (1)掌握时间片轮换的进程调度算法; (2)掌握带优先级的进程调度算法; (3)选用面向对象的编程方法。 2、实验学时:2学时 3、实验要求 (1)自定义PCB的数据结构; (2)使用带优先级的时间片轮转法调度进程,每运行一个时间片,优先级减半。 (3)命令集 A)create 随机创建进程,进程的优先级与所需要的时间片随机决定; B)ps 查看当前进程状态 C)sleep 命令将进程挂起 D)kill 命令杀死进程 E)quit命令退出 二、实验内容 根据教师指定的实验课题,完成设计、编码、测试工作。 实验三 虚拟存储器 一、目的和要求 1. 实验目的 (1)掌握先进先出页面置换算法; (2)掌握随机替换页面置换算法; (3)掌握OPT页面置换算法; (4)掌握最近最少使用页面置换算法; (5)熟悉抖动现象及其产生原理; (6)熟悉C/C++编程。 2、实验学时:2学时 3、实验要求 (1)进程占用内存空间共640K,页面大小是1K/2K/4K/8K; (2)随机生成256个页面置换次序; (3)用于分配页面大小的内存总空间是32K; (4)给出四种页面置换算法的换页过程,并计算各自的缺页率。 二、实验内容 编写程序,使用四种不同的页面替换策略算法进行页面替换。分别是先进先出,随机替换,时钟页面替换,最近最久未使用页面替换,并计算缺页率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值