Objective-C内存管理之-引用计数
本文会继续深入学习OC内存管理,内容主要参考iOS高级编程,Objective-C基础教程,疯狂iOS讲义,是我学习内存管理的笔记
内存管理
1 内存管理的基本概念
1.1 Objective-C中的内存管理
- 手动内存管理和自动释放池---
MRC
>(Mannul Reference Counting) - 自动内存管理---
ARC
>(Automatic Reference Count) - 自动垃圾回收---
GC
>(Garbage Collection)
由于iOS系统不支持垃圾回收,所以我们在iOS开发中只能使用MRC和ARC来进行内存管理,本文不再介绍Objective-C中的垃圾回收机制,但是此处注意Objective-C中是存在垃圾回收机制的
1.2 内存管理中存在的问题
内存泄露
:不再需要的对象没有释放引起的问题
:程序的内存占有量不断增加,最终会被耗尽导致程序崩溃野指针
:没有进行初始化得指针引起的问题
:浪费内存资源,如果调用程序会出现未知的结果,甚至导致程序崩溃悬空指针
:一个指针指向一个被销毁的对象引起的问题
:调用悬空指针指向的属性或者方法时,程序会出现未知的结果,甚至导致程序崩溃僵尸对象
:过度释放的对象引起的问题
:
2.手动内存管理和自动释放池---MRC
>(Mannul Reference Counting)
2.1 什么是引用计数(Reference Counting)
引用计数
:Objective-C中引入了引用计数这一机制来跟踪并处理对象的生命周期,
管理方式
:每个对象都有一个与之关联的整数,这个整数被称为引用计数,在Objective-C中,通过不同的方法可以对引用计数进行操作,具体的处理如下表:
对象操作 | Objective-C方法 | 对应的操作结果 |
---|---|---|
生成并持有对象 | alloc , new , copy ,mutableCopy 等方法 |
生成对象并设置引用计数 =1 |
持有对象 | reatain 方法 |
使引用计数 +1 |
释放对象 | release 方法 |
使引用计数 -1 |
废弃对象 | dealloc 方法---系统自动调用 |
引用计数 =0 时调用 |
关于delloc
方法:dealloc方法继承自NSObject
,因此所有的对象都具有此方法,当一个对象的引用计数为0时,也就意味着没有任何程序需要此对象,系统会回收该对象所占用的内存,在系统销毁对象之前,会自动调用该对象的dealloc方法来执行一些回收操作,如果该对象还持有其他对象的引用,我们必须重写dealloc方法来释放该对象引用的其他对象(通常就是使用该对象的release方法)
引用计数机制回收对象的说明
:如果一个对象的引用计数为0,则表明程序已经不再需要它,这时系统会自动回收该对象所占内存,相反,如果一个对象的引用计数不为0,系统就不应该回收,也不会回收它所占的内存
关于retainCount方法
:Objective-C提供了retainCount方法来返回一个对象当前的引用计数
如何重写dealloc方法
:
- (void)dealloc {
// 处理该对象的其他引用(通过release方法)
/** 回调父类的dealloc方法 */
[super dealloc];
}
2.2 苹果如何管理引用计数
- 2.2.1 因为NSObject类的源代码没有公开,我们利用Xcode的调试器(lldb)和iOS大概追溯出其实现过程
alloc
+alloc
+allocWithZone:
class_createInstance //此方法可以通过objc4中的runtime/objc-runtime-new.mm确认
calloc // 分配内存块
retainCount
-retainCount
__CFDoExternRefOperation // 此函数根据retain,retainCount,release操作进行分发,调用__CFBasicHashXXX方法
CFBasicHashGetCountOfKey
retain
-retain
__CFDoExternRefOperation
CFBasicHashAddValue
release
-release
__CFDoExternRefOperation
CFBasicHashRemoveValue // 当此函数返回0时, -release调用dealloc方法
- 2.2.2 由__CFDoExternRefOperation函数以及此函数的调用关系,我们大概推算苹果大概是使用散列表(引用计数表)来管理引用计数
- 通过引用计数表来管理引用计数的好处:
- 对象用内存块的分配无须考虑内存块头部
- 引用计数表各记录中存有内存块的地址,可从各个记录追溯到各对象的内存块(在进行内存泄露的检查时,此条特性具有举足轻重的作用,即使出现故障导致对象占用的内存块损坏,但是只要引用计数表没有被破坏,我们就可以确定各内存块的位置,这就是设置全局断点可以查出哪里出现内存泄露的原因)
- 通过引用计数表来管理引用计数的好处:
2.3 内存管理的思考方式
自己生成的对象,自己持有
1.1 使用
alloc
new
copy
mutableCopy
创建的对象只能自己持有id obj1 = [[NSObject alloc] init];
id obj2 = [NSObject new];
id obj3 = [NSObject copy];
id obj4 = [NSObject mutableCopy];
1.2 使用以上名称的开头的方法也意味着自己生成并持有对象
alloc
NewObjectnew
NewObjectcopy
NewObjectmutableCopy
NewObject非自己生成的对象,自己也能持有
2.1 非
alloc
new
copy
mutableCopy
生成的对象,变量obj本身不持有该对象id obj1 = [NSMutableArray array];
id obj2 = [NSDictionary dictionary];2.2 通过retain方法,非通过
alloc
new
copy
mutableCopy
生成的对象,可以成为自己持有的对象id obj = [NSMutableArray array]; [obj retain];
不再需要自己持有的对象时释放
3.1 释放通过
alloc
new
copy
mutableCopy
生成的对象,一旦不在需要,务必要使用release方法释放id obj = [[NSObject alloc] init]; [obj release];
3.2 用retain方法持有的非自己生成的对象,一旦不再需要,也一定要使用release释放
id obj = [NSMutableArray array];
[obj retain]; // 通过retain方法持有对象
[obj release]; // 在不需要时也要通过release方法释放对象
3.3 用某个方法生成对象,并将其作为方法的返回值,这时我们该如何处理
3.3.1 通过
alloc
new
copy
mutableCopy
或其他符合命名规则的方法生成的对象,只需要原封不动的返回就能让调用方也持有该对象- (id)allocObject {
id obj = [[NSObject alloc] init];
return obj;
} - (id)allocObjectWithObject:(id)obj {
id object = [obj allocObject];
return object;
}
3.3.2 如果持有非自己生成的对象,例如[NSMutableArray array]生成的对象,我们要使用autorelease方法释放
注:
命名规则
:用来取得谁都不持有的对象的方法名不能以alloc
new
copy
mutableCopy
开头- (id)object {
id obj = [NSMutableArray array];
[obj autorelease];
return obj;
}
3.3.3
autorelease
方法:提供了这样的功能,使对象在超出指定的生存范围时自动并正确释放(调用release方法)
非自己持有的对象无法释放---注意以下两点,如果发生这样的情况会导致程序崩溃
4.1 通过
alloc
new
copy
mutableCopy
方法或者通过retain方法持有的对象,一旦不再需要时,必须进行释放,除此之外其他方法获得的对象绝对不能释放,一旦释放会造成程序崩溃4.2 自己持有的对象释放后再次释放,造成僵死对象,引起程序崩溃或在访问废弃的对象时崩溃
id obj = [[NSObject alloc] init];
[obj release];
[obj release]; // 再次释放
Objective-C内存管理之-引用计数的更多相关文章
- iOS的内存管理和引用计数规则、Block的用法以及三种形式(stack、malloc、global)
学习内容 iOS的内存管理和引用计数规则 内存管理的思考方式 自己生成的对象自己持有 非自己生成的对象自己也能持有 自己持有的对象不需要时释放 非自己持有的对象不能释放 ARC有效时,id类型和对象类 ...
- Objective-C内存管理之引用计数
初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...
- Swift基础语法-内存管理, 自动引用计数
1. 工作机制 Swift和OC一样,采用自动引用计数来管理内存 当有一个强引用指向某一个对象时,该对象的引用计数会自动+1 当该强引用消失时,引用计数会自动-1 当引用计数为0时,该对象会被销毁 2 ...
- Python内存管理及引用计数
作为一门动态语言,python很重要的一个概念就是动态类型,即对象的类型和内存占用都是运行时确定的.(Why?)运行时,解释器会根据语法和右操作数来决定新对象的类型.动态类型的实现,是通过引用和对象的 ...
- Objective C内存管理之理解autorelease------面试题
Objective C内存管理之理解autorelease Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的A ...
- Object-C内存管理-对象引用计数的特例
看到OC中内存管理这块,其中的引用计数部分,部分10.5上的EBOOK示例已经在10.9上不能运行正确了,比如下面的代码: NSString * str1 = @"string 1" ...
- Objective C 内存管理[转]
1 配对原则 alloc – release new – release retain - release copy – release 2 new和alloc-init的区别 (1)区别只在于a ...
- objective C 内存管理及属性方法具体解释
oc为每一个对象提供一个内部计数器.这个计数器跟踪对象的引用计数,当对象被创建或拷贝时.引用计数为1.每次保持对象时,调用retain接口.引用计数加1.假设不需要这个对象时调用release,引用计 ...
- OC语法6——内存管理之引用计数器(retain,release)
OC内存管理: 一.引用计数器: Java有垃圾回收机制(Garbage Collection,GC).也就是说当我们创建对象后,不需要考虑回收内存的事,Java的垃圾回收机制会自动销毁该对象,回收它 ...
随机推荐
- 【转】java中注解的使用与实例
原文:http://www.cnblogs.com/pepcod/archive/2013/02/20/2918719.html java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单. ...
- react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...
- 【JVM】JVM系列之Class文件(三)
一.前言 随着我们学习的不断深入,我相信读者对class文件很感兴趣,class文件是用户编写程序与虚拟机之前的桥梁,程序通过编译形成class文件,class文件之后会载入虚拟机,被虚拟机执行,下面 ...
- 5.Struts.xml标签中的一些小技巧
1.为Action属性注入值如给actions包下的test.java类中变量username赋值为"xingyun"在struts.xml中添加下面这段代码: <strut ...
- 浅谈MITM攻击之信息窃取(解密315晚会报道的免费WIFI窃取个人信息)
前言 所谓的MITM攻击(即中间人攻击),简而言之就是第三者通过拦截正常的网络通信数据,并进行数据篡改和嗅探,而通信的双方毫无感知.这个很早就成为黑客常用的手段,一会聊的315晚会窃取个人信息只是 ...
- hexo在git上搭建个人博客
公司实习第一天接到的任务是:搭建一个基于Nodejs的开源项目的开发环境,接到任务时以为不是很困难,后来才知道该项目已于去年被废弃,搭配环境的时候遇到了不少问题,折腾了两天还是没有最终完成... 不过 ...
- 测试为什么Low
你从来没有因为一个歌手不会写曲填词而说歌手很Low! 你从来没有因为一个演员不会摄影.唱歌而说演员很Low! 你从来没有因为一个记者不会摄影,拍照而说记者很Low! 你从来没有因为一个美食家不会烧菜, ...
- QT QTableView用法小结
QTableView常用于实现数据的表格显示.下面我们如何按步骤实现学生信息表格: 一 添加表头 //准备数据模型 QStandardItemModel *student_model = new QS ...
- [WCF编程]6.绑定行为
一.绑定行为概述 为了支持服务端的其它本地特性,WCF定义了行为的概念.行为就是服务的本地特性,不会影响服务的通信模式.客户端并不知道服务端行为,所以行为不会出现在服务的绑定和发布的元数据中.说下WC ...
- LA4287--tarjan
题目大意: 在数学中,我们常常需要完成若干个命题的等价性证明.比如,有4个命题a,b,c,d,我们证明a↔b,然后b↔c,最后c↔d.注意每次证明都是双向的,因此一共完成了6次推导.另一种方法是a→b ...