内存管理和引用计数

ARC

在LLVM编译器中设置ARC为有效状态,就无需再次输入retain或者release代码

照明对比引用计数 对照明设备所做的动作 对oc对象所做的动作 引用技数 oc方法
第一个进入办公室的人 开灯 生成并持有对象 0 --- >1 alloc,new,copy,mutableCopy等方法
之后每当有人进入办公室 需要照明 持有对象 1 --- >2 retain方法
每当有人下班离开办公室 不需要照明 释放对象 2 --- > 1 release方法
最后一个人下班离开办公室 关灯 废弃对象 1 ----> 0 dealloc方法

alloc,retain,release,dealloc的实现总结,
1, 在oc的对象中存有应用计数这一整数值
2, 调用allocretain方法后,引用计数值加1
3, 调用release后,引用计数值减1
4, 引用计数值为0时,调用dealloc方法废弃对象

内存管理的思考方式

  • 自己生成的对象,自己所持有

    • 自己生成并持有对象的源代码

      /*  

      使用 NSObject类的alloc类方法就能自己生成并持有对象,指向生成并持有对象的指针被赋给变量obj,[NSObject new]与[[NSObject alloc]init]是完全一致的
    */
    id obj = [[NSObject alloc] init];
    id obj = [NSObject new];
  • 使用以下方法也可以生产并持有对象
alloc new copy mutableCopy

copy方法利用基于NSCopying方法约定,由各类实现的copyWithZone:方法生成并持有对象的副本.
mutableCopy方法利用基于NSMutableCopying方法约定,由各类实现的mutableCopyWithZone:方法生成并持有对象的副本.
两者的区别在于,copy方法生成不可变更的对象,而mutableCopy方法生产可变更的对象

  • 使用以下名称开头的方法名,也意味着自己生成并持有对象

    allocMyObject newThatObject copyThis mutableCopyYourObject

  • 非自己生成的对象,自己也能持有

    • 通过retain方法,非自己生成的对象跟用alloc ,new,copy,mutableCopy方法生成并持有的对象一样,成为了自己所持有的.

    • 源码展示



    /*
     NSMutableArray类对象被赋给变量obj,但变量obj自己并不持有该对象,但retain方法可以持有对象
     */
    
    id obj = [NSMutableArray array];
    [obj retain];


    ```

    

- 不再需要自己持有的对象时要释放

    - 自己持有的对象,一旦不再需要,持有者有义务释放该对象.释放使用``release``方法

        - 源码展示

```objc

          // 用alloc方法由自己生成并持有的对象就通过release方法释放了

    /* 自己生成并持有对象*/
    id obj = [[NSObject alloc] init];
    /* 释放对象,*/
    [obj release];
        


        ```

    
- 取得非自己生产并持有的对象

   - 源码展示

``` objc

        /*取得的对象存在, 自己不持有对象*/

    id obj = [NSMutableArray array];
    /* 自己持有对象*/
    [obj retain];
    /* 释放对象,对象不可再被访问*/
    [obj release];
     ```
    
- 用某个方法生成对象,并将其返还给该方法的调用方
    > 原封不动的返回用``alloc``方法生成并持有的对象,就能让调用方也持有该对象,  ``allocObject``是符合驼峰命名规范的,即将第一个词后每个词的首字母大写来拼写复合词的记法. 外部调用,``id obj1 = [obj0 allocObject];``,即自己持有对象  

    - 源码展示

``` objc

    - (id)allocObject{

        
        /* 自己生成并持有对象*/


        id obj = [[NSObject alloc] init];


        /* 自己持有对象*/
       return obj;

    }
    ```
 - 调用``[NSMutableArray array]`` 方法使取得的对象存在,但自己不持有对象
   
  > 使用autorelease方法,可以使取得的对象存在,但自己不持有对象,``autorelease``提供这样的功能,使对象在超出置顶的生存范围时能够自动并正确地释放(调用``release``方法)

- 源码展示

    ```objc

    - (id)object
    {
        /* 自己生成并持有对象*/
        id obj = [[NSObject alloc] init];
        /* 自己持有对象*/
        [obj autorelease];
        /* 取得的对象存在,但自己不持有对象 */
        return obj;
    }
  • 外部调用
// 取得的对象存在,但自己不持有对象
id obj1 = [obj0 object];
// 通过retain方法将调用autorelease方法取得的对象变为自己持有
[obj1 retain];
    ```
  • 非自己持有的对象无法释放

自己生成并持有对象后,在释放完不再需要的对象之后再次释放


    /* 自己生成并持有对象*/


    id obj = [[NSObject alloc]init];


    /* 对象已释放*/


    [obj release];


    /* 释放之后再次释放已非自己持有的对象,应用程序崩溃!


        崩溃情况: 再度废弃已经废弃了的对象时崩溃,访问已经废弃的对象时崩溃


     */


    [obj release];
  
    ```
     
   > 取得的对象存在,但自己不持有对象时释放
 
```objc


    /*取得的对象存在,但自己不持有对象*/
    id obj1 == [obj0 object];
    /* 释放了非自己持有的对象,肯定会导致应用程序崩溃*/
    [obj1 release];
    ```


# ``alloc``,``retain``,``release``,``dealloc``实现

    

> CGUstep是Cocoa框架的互换框架,从使用者的角度来看,两者的行为和实现凡是是一样的



- ``GNUstep``源代码中``NSObject``类的类方法实现

    - ``+ (id)alloc``通过``+(id)allocWithZone:(NSZone * )z``调用``NSAllocateObject``函数分配了对象,``NSAllocateObject``函数又通过调用``NSZoneMalloc``函数来分配存放对象所需的内存空间,之后将该内存空间置为0,最后返回作为对象而使用的指针

    - ``alloc``类方法用``struct obj_layout``中的``retained``整数来保存引用计数,并将其写入对象内存头部,该对象内存块全部置为0后返回

    - 对象的引用计数可通过``retainCount``实例方法取得,内部调用``NSExtraRefCount``函数,执行``alloc``后对象的``retainCount``是``1``.

    - 由对象寻找到对象内存头部,从而访问其中的``retained``变量,因为分配时全部置为0,所以``retained``为0,由``retainCount``方法内部的``NSExtraRefCount(self)+1``得出,``retainCount`为1.即``retain``方法使``retained``变量加1,而``release``方法使``retained``变量减1.



- 苹果的实现

    - ``alloc``类方法首先调用``allocWithZone:``类方法,然后调用``class_createInstance``函数,最后通过`calloc``来分配内存块

    - ``retainCount``,``retain``,``release``各方法都调用了``_CFDoExternRefOperation``函数,苹果的实现大概就是采用散列表(引用计数表)来管理引用计数



-  GNUstep和苹果实现进行对比

    - ``GNUstep``将引用计数保存在对象占用内存块头部的变量中,而苹果则是保存在引用技术表的记录中

    - 内存块管理的好处:

        > 1.少量的代码即可完成 

            2.能过统一管理引用计数用内存块与对象用内存块

    - 通过引用技术表管理引用计数的好处:

       > 1. 对象用内存块的分配无需考虑内存块头部 

        2.引用计数表各记录中存有内存块,可从各个记录追溯到各对象的内存块.

# autorelease使用

 > ``autorelease``自动释放,类似于C语音中局部变量的特性(程序执行时,若某自动变量超出其作用域,该自动变量将被自动废弃),``autorelease``会在对象实例超出其作用域时,调用对象实例的``release``方法.



 - ``autorelease``的具体使用方法如下:

    > 1.生成并持有``NSAutoreleasePool``对象

        2.调用已分配对象的``autorelease``实例方法

        3.废弃``NSAutoreleasePool``对象,将调用``release``方法



# ``autorelease``实现

   - ``GNUstep``中实现

   > ``autorelease``实例方法的本质就是调用``NSAutoreleasePool``对象的``addObject``类方法.

   - 苹果的实现

    > 1.``static inline void *push()`` 相当于生成或持有``NSAutoreleasePool``类对象

        2.``static inline void *pop(void *token)``内部为``releaseAll()``方法, 相当于废弃``NSAutoreleasePool``类对象

    3.``static inline id autorelease(id obj)``内部调用``add(obj)``方法(将对象追加到内部数组中),相当于``NSAutoreleasePool``类的``addobject``类方法



 - 相关问题

    > 如果NSAutoreleasePool对象调用 autorelease会如何?
  
  ```objc
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [pool release];

会发生异常,在使用oc的Foundation框架时,无论使用哪一个对象的autorelease实例方法,实际上都是调用NSObject类的autorelease实例方法.但是对于NSAutoreleasePool类,autorelease实例方法已被该类重载,因此运行时就会出错

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

推荐阅读更多精彩内容

  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 1,928评论 1 16
  • 1. 内总管理原则(引用计数) IOS的对象都继承于NSObject, 该对象有一个方法:retainCount...
    lilinjianshu阅读 2,142评论 0 2
  • 自动引用计数 自动引用计数:指内存管理中对引用采取自动计数的技术。 内存管理/引用计数 持有对象引起引用计数加...
    南京小伙阅读 1,291评论 2 3
  • 工作以来,大公司人事变动比较频繁,调换部门也是常有的事,也经历了好些个领导,有直接领导也有上级领导,每个领导的风格...
    亭子文阅读 3,232评论 0 0
  • 从前,有个百万富翁,每天让他劳神费心的事情跟他拥有的财富一样多。 所以,他每天都愁眉紧锁,难得有个笑脸。 百万富翁...
    奔跑影子阅读 567评论 0 3