在XCode中加入如下代码:
 UILabel *label=[UILabel alloc];
[label setText:@"TestLabel"];
NSLog(@"%d",[label retainCount]);
[label release];
NSLog(@"%d",[label retainCount]);
理论上说,第一句话alloc了一个label,其保留计数器值为1,第二句话对保留计数器的值不产生影响,第4句话release了label,其保留计数器的值应该变为0,从而调用dealloc方法销毁label,但事实上,NSLog输出的结果为:
 1
 1 
两个NSLog结果都是1,更为奇怪的是,如果在第二个NSLog之前加上一句NSLog,内容任意,如下:
UILabel *label=[UILabel alloc];
[label setText:@"TestLabel"];
NSLog(@"%d",[label retainCount]);
[label release];
NSLog(@"Anything Else");
NSLog(@"%d",[label retainCount]);
 
此时,原来的第二个NSLog会出现EXEC_BAD_ACCESS错误,如下:
self.window.rootViewController * self.viewController;   EXC_BAD_ACCESS 错误
NSLog输出结果为:
1
Anything Else
...错误代码.....
 
这里虽然出现了错误,但这样的结果反而是正确的,因为在NSLog之前,label已经被dealloc,这时发送给label的消息应该都不能被响应,会出现EXEC_BAD_ACCESS错误;但是,为什么之前第一种代码写法不是这样的情况呢?
根据网上查阅的资料,也许可以得出以下结论,事实上label的确已经被dealloc了,保留计数器的值也已经变成0了,其原来占用的内存也已经不可用 了,但是原来这块内存中的内容还没有变(标记删除),将会在未来某个不确定的时间上被清理 ,这就是为什么NSLog输出的label保留计数器的值仍为1,而如果在此 之前再加上一个NSLog,则改变了原来这块内存的内容,于是发送给label的消息不再会被响应,于是程序crash。
值得一提的是,并不是加了一句NSLog之后就一定会造成程序crash的,如果那句新加的NSLog没有占用原来label的内存,那下一句NSLog依旧能够响应发送给label的消息,结果会类似第一种代码所产生的结果,具体如下:
1
Anything Else
1
 
所以说,两种情况都是有可能发生的,至于到底发生哪种情况,完全取决于合适系统清理掉label占用的内存,也可以说取决于“运气”,因为这个时间是不确定的。由于苹果源码非开源,所以究竟是什么样的都知识猜测,以上内容皆网上结果,本人认为retaincount最后为1.永远不可能为0.具体论证如下:
老师模拟了release内部实现大致算法:
release()
{
if(retainCount>1)
retainCount--;
else
{dealloc();}
}
 
于是可以看出retainCount最终为1的时候执行了dealloc();dealloc在类中实现了重写,所以retainCount=1的时候进行了release()会自然的想到retainCount=0,这是多数人的自然思维.其实retainCount=1的时候进行release()就会执行dealloc(),外部实现了重写dealloc()方法,所以这就是为什么程序retainCount=1的时候再次release()就会销毁程序然后系统自然调用dealloc()的原因.
比如:

Student *stu=[Studentnew];//retainCount=1

[stu retain];  //retainCount=2;

[stu release];//执行如 release(){if(retainCount>1)retainCount--;else{dealloc();}}的操作   retainCount=1

[stu release];//执行如 release()内部的else中的操作 调用dealloc()方法,外部实现了重写,故:调用dealloc();  此时retainCount=1 .

如果不加僵尸模式可以测试出来,在dealloc()函数中NSLog();一下,可以输出两次结果.

为什么可以输出两次结果而不是三次四次?请看如下dealloc实现代码:

-(void)dealloc

{    NSLog(@"------->AA");

[super dealloc];//调用了父类的dealloc();

}

以上重写的dealloc()函数内部进行了父类的dealloc()方法调用,第一次retainCount=1的时候进行release(),会正常执行dealloc()并打印结果,此时进行了 [super dealloc];父类被销毁,清空内存中内容,标记删除.当再次执行release()的时候,retainCount=1不变,进行else中内容的操作,执行dealloc(),dealloc()函数内容还是先NSLog();输出的时候没有问题,当执行到 [super dealloc];的时候才出问题,说明程序crash掉是因为父类被dealloc()的缘故,但是retainCount的值仍然是1.根据super()的dealloc情况而确定是否crash程序,海阔天空,真相大白了吧!!!大笑三声哈哈哈.......

Object -c基础知识(5)--release 之后 retainCount为何为1的更多相关文章

  1. Object c 基础知识

    文件类型说明:.h 头文件,用于定义类.实例变量及类中的方法等定义信息(interface)..m 源文件,定义方法体,可实现objce-c和c方法(implementation)..mm c++源文 ...

  2. 第二十九节:Java基础知识-类,多态,Object,数组和字符串

    前言 Java基础知识-类,多态,Object,数组和字符串,回顾,继承,类的多态性,多态,向上转型和向下转型,Object,数组,多维数组,字符串,字符串比较. 回顾 类的定义格式: [类的修饰符] ...

  3. Object c 基础知识

    文件类型说明:.h 头文件,用于定义类.实例变量及类中的方法等定义信息(interface). .m 源文件,定义方法体,可实现objce-c和c方法(implementation). .mm c++ ...

  4. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  5. .NET Framework基础知识总结

    之前给大家总结了java的面试几次技巧总结,同学们看了觉得还是不错,能够得到大家的认可,感觉还是挺不错的.现在又有同学来想小编索要.NET面试的总结了,好吧.谁让小编这么好呢!以下是.NET面试之框架 ...

  6. 【RAC】RAC相关基础知识

    [RAC]RAC相关基础知识 1.CRS简介    从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁. ...

  7. C#基础知识汇总(不断更新中)

    ------------------------------目录---------------------------- 1.隐式类型2.匿名类型3.自动属性4.初始化器5.委托6.泛型7.泛型委托8 ...

  8. SpringMVC(一) 基础知识+入门案例

    SpringMVC基础知识 1.什么是Springmvc 2.springmvc 框架的原理(必须掌握) 前端控制器.处理器映射器.处理器适配器.视图解析器 3.SpringMVC 入门程序 目的:对 ...

  9. Windows_Program_Via_C_Translate_Win32编程的背景知识/基础知识_包括基本输入输出机制介绍

    Some Basic Background Story of The Win32 APIs Win32 API背景故事/背景知识 The Win32 application programming i ...

随机推荐

  1. 华中农业大学预赛 B Handing Out Candies 余数的和

    Problem B: Handing Out Candies Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 258  Solved: 19[Submit ...

  2. ci与cd的全称

    Continuous Integration (CI) / Continuous Delivery (CD)

  3. 使用tk.mybatis快速开发curd

    使用mybatis已经是可以快速开发程序了,对于单表的curd似乎是一种可抽象的结果,下面介绍tk.mybatis的使用方式. maven引用 我使用的是这个版本,所以相关功能介绍也是这个版本. 使用 ...

  4. AngularJs filter 过滤器基础【转】

    Filter Ng里的过滤器. currency:把一个数字格式化成货币模式(如$1,234.56).当没有提供任何货币符号时,默认使用当前区域的符号. 使用: HTML:{{ currency_ex ...

  5. 雷林鹏分享:C# 反射(Reflection)

    C# 反射(Reflection) 反射(Reflection) 对象用于在运行时获取类型信息.该类位于 System.Reflection 命名空间中,可访问一个正在运行的程序的元数据. Syste ...

  6. AC自动机练习

    多模板串匹配一般有两种方法 暴力kmp, 适用于模板串少的情形 直接trie上暴力, 适用于模板串比较短的情形, 并且可以动态插入合并 建立AC自动机, 复杂度是严格线性的, 但不能动态插入 cons ...

  7. LeetCode 318. Maximum Product of Word Lengths (状态压缩)

    题目大意:给出一些字符串,找出两个不同的字符串之间长度之积的最大值,但要求这两个字符串之间不能拥有相同的字符.(字符只考虑小写字母). 题目分析:字符最多只有26个,因此每个字符串可以用一个二进制数来 ...

  8. Leetcode 86

    /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...

  9. 记一次使用utl_http方法调用接口,报字符或值错误

    背景:ebs系统和其他系统通过utl_http包调用接口,使用log方法记录日志. 某次调用接口,执行到记录日志行报字符或值错误. 查找原因,发现是p_str的长度超过的32767的限制. 解决办法: ...

  10. java.security.cert.CertificateException: No subject alternative names present

    背景:在开发一个项目中,要调用一个webservice服务,之前设置的是http协议,项目中采用jdk自带的wsimport工具生成的客户端代码; 后来,需求变更要求兼容https协议的webserv ...