OC内存管理

01 概述

1.内存中有五大区域,为什么只需要关心堆区?

1)堆区存的是对象,对象占的区域可能会很大
2)堆区的对象不会自动释放,需要手动管理,如果不进行管理,那么会直到程序结束的时候才会释放

2.什么时候释放堆区的对象

1)当这个OC对象没有"人"使用的时候,可以释放
2)当这个OC对象有"人"使用的时候,千万不要释放
注意:"人"表示对象的使用者

3.如何判断一个OC对象是否有人使用

1.每一个OC对象都有一个引用计数器(retainCount),表示对象的使用者的个数
2.每当创建一个新的对象,retainCount值默认是1
3.每当多一个人要使用对象的时候,retainCount+1
4.每当少一个人要使用对象的时候,retainCount-1
5.当retainCount=0的时候,系统会立即回收该对象,同时给对象发送dealloc消息

4.程序员如何控制retainCount值?

1.向对象发送release消息,让对象的retainCount-1
2.向对象发送retain消息,让对象的retainCount+1
3.向队形发送retainCount消息,获得对象的retainCount值
4.所谓的消息,其实就是对象的方法
所有和内存管理相关的成员变量以及方法,都是定义在NSObject类中的

5.内存管理的分类

1.MRC,手动引用计数,程序员需要手动管理对象的retainCount值,
2.ARC,自动引用计数,编译器帮我们管理对象的retainCount值
3.ARC和MRC的关系

1.ARC是基于MRC的
2.ARC是编译器特性,编译器在编译的时候,会在合适的位置,自动插入内存管理的代码
3.ARC是2011年iOS5出现,是程序员的一大福音,省去了很多繁琐的内存管理的工作
4.从Xcode6开始,新建的项目默认都是ARC的

6.MRC是ARC的底层原理

只有理解MRC才能更好的理解内存管理的原理

02 MRC程序

1.如何关闭ARC机制,把项目设置为MRC

在项目信息页面,选择BuildSettings,搜索auto,找到"A...R...C...",默认是YES,改成NO即可.
注意:如果在ARC环境下,不能使用内存管理的方法,否则编译器会报错.

2.为什么我们重写dealloc方法的时候,需要在最后调用父类的dealloc方法?

重写init方法的时候

1.父类的init方法实现默认有一些初始化对象时必须的操作
2.需要在父类init方法的基础之上增加一些操作,这个时候需要先调用父类中init方法实现

重写dealloc方法的时候

1.父类的dealloc方法实现中默认有一些对象释放的是否必须的操作,一旦调用了NSObject类中dealloc方法的实现,那么对象就会被彻底的释放
2.我们在对象彻底释放之前可能还需要对对象做一些事情,比如说需要先释放当前对象中特有一些内容,在完成这些操作之后,再调用父类中dealloc方法的实现

3.注意点:

1.重写dealloc方法的时候,必须在最后调用父类中dealloc方法的实现(MRC)
2.dealloc方法不需要手动调用,当对象销毁的时候系统会自动调用该对象的dealloc方法,千万不要手动调用
3.对象调用release方法之后就会销毁吗?
不一定,release方法只会让当前对象的引用计数器-1,和销毁对象之间没有什么必然联系

在MRC中判断对象是否销毁只有一个原则,就是对象的引用计数器是否为0

03 内存管理的原则

1.保持平衡

1.有new\alloc,就必须要有release
2.有retain,就必须要有release
3.谁new\alloc,谁release
4.谁retain,谁release

// 2.使用哪个指针给对象发送了new/alloc消息,就需要通过这个指针发送release
// 3.使用哪个指针个对象发送了retain消息,就需要通过这个指针发送release

Person *p1 = [[Person alloc] init];  //1
//[p1 release];

//Person *p2 = p1;
//[p2 retain];
// retain内部把当前对象的retainCount+1,然后返回当前对象

Person *p2 = [p1 retain];  // 2

[p1 release] // 1
[p2 release] // 0 -> 由系统调用dealloc方法,释放对象

//
//Person *p2 = [p1 retain];
//Person *p3 = p1;
//
//[p1 release];
//[p2 release];

04 野指针与僵尸对象

在OC中

1.对象的回收

1.一旦对象回收,说明对象在内存中占有的堆区空间,可以分配给别人使用(不代表空间被删掉,也不代表立刻分配给被人使用)
2.但是在系统把该空间分配给其他人使用之前,对象还存在(对象中的数据还存在)

2.僵尸对象

对象已经被回收了,但是对象的数据还存在内存中,这样的对象叫做僵尸对象

注意点:

1.当僵尸对象占用的空间,系统没有分配给其他人使用的时候,这个对象其实还存在,还可以访问
2.当僵尸对象占用的空间,系统已经分配给其他人使用的时候,这个对象不存在,不可以访问
3.严格意义上来说,对象一旦成为了僵尸对象,无论如何不能访问
4.僵尸对象无法复活(不应该调用僵尸对象的方法)

Xcode中开启僵尸对象检测

默认没有开启,避免浪费性能
Edit Scheme -> Diagnostics -> 勾选Enable Zombie Object

3.野指针

指向被回收对象的指针,叫做野指针
指向堆区僵尸对象的栈区指针变量,叫做野指针

4.如何防止野指针错误
Person *p1 = [[Person alloc] init]; // 1
[p1 release] // 0
// p1是一个野指针,p1指向的堆区对象是僵尸对象
p1 = nil;

[nil sayHi];

05 单个对象的内存管理

int main() {
    Person *p1 = [Person new];
}
1.如何避免内存泄漏

1.retain和release一定要匹配
2.不要让指针随便指向nil

06 多个对象的内存管理之一

1.当对象A中拥有一个成员变量是对象B,如果A没有释放,那么B就不能是释放.因为B作为A的成员变量,说明A随时都有可能使用B,那么必须当A释放的时候,才能把B释放.

演化步骤:

1.创建对象A, 创建对象B
2.把B对象设置给A对象,
出现的问题:当B对象释放之后,A对象就无法再使用B对象

解决方案:

3.在把B对象设置给A的时候,让B对象的引用计数器+1,说明A对象拥有B对象
出现的问题:当A对象释放之后,B对象无法释放
解决方案:
4.当A对象销毁的时候,也就是在A对象的dealloc方法中,先让B对象的引用计数器-1,再释放A对象

07 多个对象的内存管理之二

出现的问题:

如果给A类对象a中的B类型的成员变量更换了一个值,从b对象换成了b1,此时在a对象销毁的时候,释放的是b1,而无法释放b,导致b内存泄漏

解决方案:

5.在B类型成员变量的set方法中,先release旧对象b,再retain新对象b1

08 回收分析

两个A类型的不同对象a和a1,同时拥有一个B类型的成员和变量b,没有出现任何问题

09 多个对象的内存管理之三

出现的问题:

如果给A类对象a中的B类型成员变量重复赋同一个值,之前是b,再赋一次b
因为在B类型的成员变量set方法中,是先release再retain,此时有可能导致b对象在release之后已经释放,变成僵尸对象,再进行retain操作会造成野指针错误

解决方案:

6.在B类型成员变量的set方法中,需要进行判断,如果是相同对象什么都不做,如果不是相同对象,先release旧对象,再retain新对象.

- (void)setB:(B *)b {
    if (_b != b) {
        [_b release];
        _b = [b retain];
    }
}

- (void)dealloc {
    [_b release];
    [super dealloc];
}

10 当属性的类型是OC对象的时候,setter方法的写法

注意:

当成员变量是OC对象的时候,它的set方法才需要按照以上总结的内容来写.
当成员变量是基本数据类型的时候,直接赋值即可.

11 @property参数之与多线程相关的

多线程相关

  1. atomic(默认值) 安全的
  1. nonatomic 不安全的

12 @property参数之与生成setter方法实现相关的

在MRC下和内存管理相关的参数

assign(默认)
retain
如果成员变量是OC对象,使用retain
如果成员变量是非OC对象,使用assign

13 @property其他参数

1.读写相关的

1.readwrite(默认),可读可写,会同时生产getter和setter
2.readonly,只读,只会生产getter,而不会生成setter

2.指定setter和getter名字

注意:

1.如果需要设置setter的名字,一定要加:.但是无论如何都不要更改setter的名字
2.如果成员变量是BOOL类型,getter一般以is开头,增加可读性
3.只是改变了setter和getter的名字,并没有改变内部实现

14 @property参数使用注意

1.在使用@property的时候,必须要加参数

1.每种类型的参数,同时只能存在一个
2.至少需要两类:线程相关的,内存管理相关的
规范写法:@property (nonatomic, retain) NSString *name;

2.如果在MRC环境下

当使用@property定义属性的时候,如果使用reatin,只会在setter中生成标准的MRC内存管理代码
但是dealloc中对该成员变量,并没有release,需要我们自己来做

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 今天看到一篇不错的文章关于OC内存管理的,转载一下与你共享概述我们知道在程序运行过程中要创建大量的对象,和其他高级...
    niceSYT阅读 407评论 0 2
  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 1,867评论 1 16
  • OC内存管理一、基本原理(一)为什么要进行内存管理。由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制...
    ScaryMonsterLyn阅读 497评论 0 3
  • ARC 一、简介 在Objective-C中采用Automatic Reference Counting (ARC...
    伶俐ll阅读 1,609评论 0 3
  • 如果能再见你一面 我想被你拥入怀中 不想听你说好久不见 你应该说 我一直在等你 那么 我来了 你在哪? 时间是一名...
    好梦从未成真阅读 508评论 0 0