首先通过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实现的更多相关文章

  1. alloc retain release函数

  2. OC语法6——内存管理之引用计数器(retain,release)

    OC内存管理: 一.引用计数器: Java有垃圾回收机制(Garbage Collection,GC).也就是说当我们创建对象后,不需要考虑回收内存的事,Java的垃圾回收机制会自动销毁该对象,回收它 ...

  3. (转)IOS内存管理 retain release

    obj-c本质就是"改进过的c语言",大家都知道c语言是没有垃圾回收(GC)机制的(注:虽然obj-c2.0后来增加了GC功能,但是在iphone上不能用,因此对于iOS平台的程序 ...

  4. ios中的关键词retain release

    内存分析  在函数中只要用new  alloc  copy  这样的分配空间时 则计算器retain就要为一 每调用一次就要加一 在.m文件中引用手动计数时 一定要调用[super dealloc]这 ...

  5. 内存管理1 retain & release

    内存管理法则 1:谁创建谁释放alloc /new/ copy------>release/autorelease.一一对应,不是你创建的就不用你释放. 2:除了alloc /new/ copy ...

  6. Alloc and release

    https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractic ...

  7. 浅谈cocosd之autorelease\retain\release的理解

    三种情况,引出问题:   1) new出来的对象需要释放,而释放时,如果有其他人引用了这个对象,再次使用这个对象时,则会出现野指针情况. ==> 于是出现了引用计数的释放管理机制. 2) 对于一 ...

  8. 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 ...

  9. 2016 - 2 - 19 ARC内存管理知识总结(一,arc基本概念及alloc等方法的实现)

    一. ARC的基本概念 1. 在objc中采用automatic reference counting 机制, 让编译器来进行内存管理.在降低程序崩溃,内存管理泄漏等风险的同时,很大程度减少了程序员的 ...

随机推荐

  1. [ CodeVS冲杯之路 ] P3143

     不充钱,你怎么AC? 题目:http://codevs.cn/problem/3143/ 大水题一道,只要会遍历,这里讲一下思路 先序遍历:先输出,然后左儿子,最后右儿子 中序遍历:先左儿子,再输出 ...

  2. 转载:Posix线程编程指南(2)

    概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.但有时应用程序设计中有必要提供 ...

  3. 《Linux命令、编辑器与shell编程》第三版 学习笔记---000

    Linux概述 1.具有内核编程接口 2.支持多用户(同时) 3.支持多任务 4.支持安全的分层文件系统 a.标准 b.链接 c.权限 5.shell(命令解释器和编程语言) a.文件名生成(通配符和 ...

  4. Video for Linux Two API Specification Revision 2.6.32【转】

    转自:https://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html Video for ...

  5. android与PC直连的socket问题

    关键字:abdroid 模拟器 socket 突然有人说使用android的模拟器做socket服务器,PC做客户端,使用UDP通信的时候,android端无法收到数据包.反过来没问题,我觉得这怎么可 ...

  6. 申请免费ssl证书

    #安装certbotyum install epel-releaseyum install certbot#配置nginx,到需要申请证书的配置文件里添加location ^~ /.well-know ...

  7. python笔记-冒泡排序【转载】

    本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/python/ 前言 面试的时候经常有面试官喜欢问如何进行冒泡排序?这个问题相信能难倒一 ...

  8. 处理下最近的file_id小写问题

    update t_resource_info set FILE_ID = UPPER(FILE_ID);update t_resource_my_info set FILE_ID = UPPER(FI ...

  9. Cannot read property 'field' of undefined (at _8 (jquery.numberbox.js:33))

    问题描述: 页面端用了easyui的numberbox属性,然后在用js的方法修改值的时候,明明看到页面中的值是数字型(数量字段), 但是就是会报错 这种错误真的是很难理解,不过经过我的debug跟了 ...

  10. AtCoder - 3962 Sequence Growing Hard

    Problem Statement Find the number of the possible tuples of sequences (A0,A1,…,AN) that satisfy all ...