深入解析alloc/retain/release/dealloc实现
首先通过GNUstep上得源码来叙述各个函数的实现(GNUstep是Cocoa框架的互换框架,二者的行为和实现方式很相似)
GNUstep源码中NSObject类的alloc方法:
id = obj = [NSObject alloc];
/**********************************/
+(id) alloc{
return [self allocWithZone : NSDefaultMallocZone()];
}
+(id) allocWithZone:(NSZone *) z{
return NSAllocateObject(self,0,z);
}
//NSZone是为了防止内存碎片化而引入的结构,对内存分配的区域本身进行多重画管理
NSAllocateObject函数例如以下:
struct obj_layout{
NSUInteger retained;
}
inline id NSAllocateObject(Class aClass,NSUInteger extraBytes,NSZone *zone){
int size =
计算容纳对象所需的内存;
id new = NSZoneMalloc(Zone ,size);
memset(new ,0 ,size);
new = (id) &((struct obj_layout *) new)[1];
}
NSAllocateObject函数通过调用NSZoneMalloc函数来分配存放对象所需的内存空间,之后将该内存空间置为0,最后返回对象而使用的指针.
/**************************/
-(NSUInteger) retainCount{
return NSExtraRefCount(self) + 1;
}
inline NSUInteger NSExtraRefCount(id anObject){
return ((struct obj_layout *) anObject)[-1].retained;
//由对象寻址找到对象内存头部,从而訪问当中的retained变量
}
/***************************/
-(id) retain{
NSInCrementExtraRefCount(self);
return self;
}
inline void NSInCrementExtraRefCount(id anObject){
if((( struct obj_layout *) anObject)[-1].retained == UINT_MAX - 1){
[NSException raise:NSInternalInconsistencyException format:@“NSIncrementExtraRefCount()ask to increment too far”];
(( struct obj_layout *)anObject) [-1].retained++;
}
}
/********************************/
-(void) release{
if(NSDecrementExtraREfCountWasZero(self))
[self dealloc];
}
BOOL NSDecrementExtraREfCountWasZero(id anObject){
if((struct obj_layout *) anObject)[-1].retained == 0){
return YES;
}else{
(struct obj_layout *) anObject)[-1].retained—;
return NO;
}
}
/**********************************/
-(void ) dealloc{
NSDeallocateObject(self);
}
inline void NSDeallocateObject(id anObject){
struct obj_layout *o = &((struct obj_layout *) anObject)[-1];
free(o);
}
以上就是GNUstep中的实现
//////////////////////////////////////////////////////////////////////////
苹果的实现
通过在NSObject类的alloc类方法上设置断点,查看其运行的函数为:
+alloc
+allocWithZone
class_createInstance
calloc
各个方法都调用了_CFDoExternRefOperation函数
/************************************************/
int _CFDoExternRefOperation(uintptr_t op,id obj){
CFBasicHashRef table =
取得对象所相应的散列表(obj);
int count;
int count;
switch (op) {
case OPERATION_retainCount:
count = CFBasicHashGetCountOfKey(table, obj);
return count;
case OPERATION_retain:
CFBasicHashAddValue(table, obj);
return obj;
case OPERATION_release:
count = CFBasicHashRemoveValue(table, obj);
return 0 == count;
}
}
何为散列表
散列表(也叫哈希表)是一种查找算法,与链表、树等算法不同的是。散列表算法在查找时不须要进行一系列和keyword(keyword是数据元素中某个数据项的值,用以标识一个数据元素)的比較操作。
散列表算法希望能尽量做到不经过不论什么比較。通过一次存取就能得到所查找的数据元素,因而必需要在数据元素的存储位置和它的keyword(可用key表示)之间建立一个确定的相应关系,使每一个keyword和散列表中一个唯一的存储位置相相应。因此在查找时,仅仅要依据这个相应关系找到给定keyword在散列表中的位置就可以。这样的相应关系被称为散列函数(可用h(key)表示)。
依据设定的散列函数h(key)和处理冲突的方法将一组keywordkey映像到一个有限的连续的地址区间上,并以keyword在地址区间中的像作为数据元素在表中的存储位置,这样的表便被称为散列表,这一映像过程称为散列,所得存储位置称为散列地址。
由上可知苹果是将计数器保存在引用记数表的记录中
优点:
(1) 对象用内存块的分配无需考虑内存头部
(2) 引用计数表个记录中存有内存块地址,可追溯到个内存块.
深入解析alloc/retain/release/dealloc实现的更多相关文章
- alloc retain release函数
- OC语法6——内存管理之引用计数器(retain,release)
OC内存管理: 一.引用计数器: Java有垃圾回收机制(Garbage Collection,GC).也就是说当我们创建对象后,不需要考虑回收内存的事,Java的垃圾回收机制会自动销毁该对象,回收它 ...
- (转)IOS内存管理 retain release
obj-c本质就是"改进过的c语言",大家都知道c语言是没有垃圾回收(GC)机制的(注:虽然obj-c2.0后来增加了GC功能,但是在iphone上不能用,因此对于iOS平台的程序 ...
- ios中的关键词retain release
内存分析 在函数中只要用new alloc copy 这样的分配空间时 则计算器retain就要为一 每调用一次就要加一 在.m文件中引用手动计数时 一定要调用[super dealloc]这 ...
- 内存管理1 retain & release
内存管理法则 1:谁创建谁释放alloc /new/ copy------>release/autorelease.一一对应,不是你创建的就不用你释放. 2:除了alloc /new/ copy ...
- Alloc and release
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractic ...
- 浅谈cocosd之autorelease\retain\release的理解
三种情况,引出问题: 1) new出来的对象需要释放,而释放时,如果有其他人引用了这个对象,再次使用这个对象时,则会出现野指针情况. ==> 于是出现了引用计数的释放管理机制. 2) 对于一 ...
- Linked dylibs built for GC-only but object files built for retain/release for architecture x86_64
编译开源Xcode 插件 SCXcodeSwitchExpander 源码地址: https://github.com/stefanceriu/SCXcodeSwitchExpander 编译环境:X ...
- 2016 - 2 - 19 ARC内存管理知识总结(一,arc基本概念及alloc等方法的实现)
一. ARC的基本概念 1. 在objc中采用automatic reference counting 机制, 让编译器来进行内存管理.在降低程序崩溃,内存管理泄漏等风险的同时,很大程度减少了程序员的 ...
随机推荐
- DataTable转换为实体集合
using System; using System.Collections; using System.Collections.Generic; using System.Data; using S ...
- Oracle 整理
高效分页 select * from ( select rownum r,a from yourtable order by name ) --之所以没有把<=20放在最外面,也就是我一直用的写 ...
- scrapy爬取段子
scrapy.py 1.cmd运行scrapy shell http://www.baidu.com response.xpath('//div[@aa="bb"]') 找到需要匹 ...
- ZOJ 3820:Building Fire Stations(树的直径 Grade C)
题意: n个点的树,边长全为1,求找出两个点,使得树上离这两个点距离最远的那个点,到这两个点(中某个点就行)的距离最小. 思路: 求树直径,找中点,删除中间那条边(如果直径上点数为奇数,则删任何一侧都 ...
- django怎么自己创建一个中间件
中间件是什么? 中间件是类似flask函数中钩子函数的东西.可以在请求视图函数前,或者视图函数响应后处理某些事情.中间件对全部视图都有效! 中间件一般会有两个方法,process_request和pr ...
- 【linux高级程序设计】(第十一章)System V进程间通信 4
共享内存 共享内存主要用于实现进程间大量数据传输. 共享内存的数据结构定义: 系统对共享内存的限制: 共享内存与管道的对比: 可以看到,共享内存的优势: 1.共享内存只需复制2次,而管道需要4次 2. ...
- springBoot Feign Hystrix
1.引入依赖包 <!-- 引入关于 hystrix的依赖 --> <dependency> <groupId>org.springframework.cloud&l ...
- 牛客网 暑期ACM多校训练营(第二场)J.farm-STL(vector)+二维树状数组区间更新、单点查询 or 大暴力?
开心.jpg J.farm 先解释一下题意,题意就是一个n*m的矩形区域,每个点代表一个植物,然后不同的植物对应不同的适合的肥料k,如果植物被撒上不适合的肥料就会死掉.然后题目将每个点适合的肥料种类( ...
- CONTINUE...?【构造/分析】
CONTINUE...? Time Limit: 1 Second Memory Limit: 65536 KB Special Judge DreamGrid has classmates numb ...
- Codeforces 914D Bash and a Tough Math Puzzle (ZKW线段树)
题目链接 Round #458 (Div. 1 + Div. 2, combined) Problem D 题意 给定一个序列,两种询问:单点修改,询问某个区间能否通过改变最多一个数使得该区间的 ...