Objective-C中release和nil的关系
注意到经常有一个这样的问题:某指针对象先release后=nil,这里后跟个=nil有什么作用?不写行不行?
简单一点说是,release是用来释放内存,nil是将对象指针设为null,nil本身对内存没什么影响,但他处理指针,尤其是避免野指针倒是很有必要。
举一个例子:
NSString *str=[[NSString alloc] init];
当我不需要str时
执行[str release];
str 的retain值减1,但是如果当前retain值>0,却紧随其后加一句str=nil;那么这时[str retainCount]应该为0,因为[nil retainCount]==0;但这时很明显存在内存泄露。
所以一个很好的写作习惯是:
当对象的retainCount==1时,写完[str release];后接着写上str=nil; 这样,当在后面的代码再次调用str相关的方法属性,也不会报错,因为之前已经将str设置为空指针,再调用str的方法也会被认为是null,不会真正调用,更不会报错。
例如下列代码:(以下所有代码段都已经过实际操作验证)
- UIView *view1=[[UIView alloc] init];
- UIView *view2=[view1 retain];
- int i=[view1 retainCount];
- NSLog(@"i:%d",i);
- [view1 release];
- view1=nil;
- [view1 addSubview:view2];
整个程序运行,是不会crash的。但是存在内存泄露。
但是,现在又有另外一个问题,请看下列代码:
- UIView *view1=[[UIView alloc] init];
- UIView *view2=[view1 retain];
- int i=[view1 retainCount];
- NSLog(@"i:%d",i);
- [view1 release];
- view1=nil;
- [view1 addSubview:view2];
- i=[view1 retainCount];
- NSLog(@"i:%d",i);
- i=[view2 retainCount];
- NSLog(@"i:%d",i);
- [view2 release];
- i=[view2 retainCount];
- NSLog(@"i:%d",i);
请问终端输出的log应该是什么?
第一个i=2,没问题,因为view1 init了一次,retain了1次,retain值为2。
第二个i=0,根据上面所讲的推断,也没问题,因为之前view1=nil,空指针的retainCount值为0。
第三个i=1,也没什么问题,因为view2是一个被赋了值的新指针,它不同于指针view1,二者是2个独立的指针,而且,view2还被赋了值分配了内存地址。
但是,第四个i呢?i=?
答案是i=1。为什么会这样?下面是真实输出结果:
- 2011-12-09 01:17:07.364 ReleaseNildemo[19115:f803] i:2
- 2011-12-09 01:17:07.365 ReleaseNildemo[19115:f803] i:0
- 2011-12-09 01:17:07.366 ReleaseNildemo[19115:f803] i:1
- 2011-12-09 01:17:07.367 ReleaseNildemo[19115:f803] i:1
为什么会这样?按推理说,程序执行到输出这句应该crash才对,我运行了好几遍,确实没有出现。晚上在网上和其他程序员讨论这个问题,有人运行的情况是“有时候会crash,有时候不会。断点的话不会crash”,最后大家讨论的话题开始变成“系统是先输出还是先回收?”,更有甚者,有人输出了一下内存地址,发现是view2 release前后输出的是同一个内存地址,说明,这个东西内存虽然释放了,但是系统还没来得及回收。
有时候crash,原因是你向一块未申请的内存发送了一条消息,最终成了系统回收速度问题了,所以,个人认为,以后碰到类似这种问题,干脆手动init,release,至少这样能很快释放,更便于清楚当前对象的内存情况。
以上是我对release nil操作的一些理解,欢迎更多人加入讨论
Objective-C中release和nil的关系的更多相关文章
- Objective C 中的nil,Nil,NULL和NSNull理解
kenyo网友的原创说法是:做IOS开发的估计都对Objective-C的内存管理机制很头疼,一不小心程序就会出内存泄露,我也不例外,前几天被指针的置nil与release给搞惨了,今和大家详细解说一 ...
- Objective-C 中 NULL、nil、Nil、NSNull 的定义及不同
本文由我们团队的 康祖彬 童鞋撰写,这是他的个人主页:https://kangzubin.cn. 理解"不存在"的概念不仅仅是一个哲学的问题,也是一个实际的问题.我们是有形宇宙的居 ...
- Python类中super()和__init__()的关系
Python类中super()和__init__()的关系 1.单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(sel ...
- 转iOS中delegate、protocol的关系
iOS中delegate.protocol的关系 分类: iOS Development2014-02-12 10:47 277人阅读 评论(0) 收藏 举报 delegateiosprocotolc ...
- 理解Objective C 中id
什么是id,与void *的区别 id在Objective C中是一个类型,一个complier所认可的Objective C类型,跟void *是不一样的,比如一个 id userName, 和vo ...
- 浅谈Objective—C中的面向对象特性
Objective-C世界中的面向对象程序设计 面向对象称程序设计可能是现在最常用的程序设计模式.如何开发实际的程序是存在两个派系的-- 面向对象语言--在过去的几十年中,很多的面向对象语言被发明出来 ...
- java中接口与多重继承的关系
在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力.abstract class和int ...
- C/C++中数组与指针的关系探究
数组与指针 长期以来,在C/C++中,数组名和指向数组首元素的指针常量到底是以一种什么关系,一直困扰着很多人.很多地方,甚至是一些教科书中都在说,"数组名就是一个指向数组首元素的指针常量&q ...
- 计算机基础--Java中int char byte的关系
计算机基础--Java中int char byte的关系 重要:一个汉字占用2byte,Java中用char(0-65535 Unicode16)型字符来存字(直接打印输出的话是字而非数字),当然要用 ...
随机推荐
- logstash 处理tomcat access报ArgumentError: comparison of String with 5 failed
<pre name="code" class="html"> 10.168.102.19 - - [22/Sep/2016:20:35:11 +08 ...
- Asp.Net 构架(Http Handler 介绍) - Part.2
原文地址:http://www.cnblogs.com/JimmyZhang/archive/2007/09/15/894124.html 引言 在 Part.1 Http请求处理流程 一文中,我们了 ...
- Java中BigDecimal的8种舍入模式是怎样的
Java中BigDecimal的8种舍入模式是怎样的?下面长沙欧柏泰克软件学院和大家一起来学习下吧: java.math.BigDecimal 不可变的.任意精度的有符号十进制数.BigDecima ...
- 在 IIS 上创建 FTP 站点
微软参考文档: 在 IIS 上生成 FTP 站点 主要过程: 1.控制面板 -> 程序 -> 启动或关闭Windows功能 -> 将Internet Information Serv ...
- ashx调用session对象
1.引入命名空间 using System.Web.SessionState 2.必须实现接口 public class Login : IHttpHandler, IRequiresSessionS ...
- Jquery:强大的选择器<一>
今天回家之后,学习的是Jquery的选择器.选择器作为Jquery的优势之一,确实让我感觉到了它的强大.Jquery选择器分为基本选择器.层次选择器.过滤选择器和表单选择器,下面我一一介绍这四种选择器 ...
- Windows命令行(DOS命令)教程-8 (转载)http://arch.pconline.com.cn//pcedu/rookie/basic/10111/15325_7.html
15. pass [功能] 设定DOS寻找.COM..EXE..BAT文件的所在目录 [格式] path=[[drive:]path[;-]]或path [说明] 只打path没有参数时,只显示环境变 ...
- 委托,匿名方法,Lambda,泛型委托,表达式树
一.委托:完成一个委托应分三个步骤://step01:首先用delegate定义一个委托;public delegate int CalculatorAdd(int x, int y);//step0 ...
- 一行代码设置UITableView分割线的长度
使用UITableView时会发现分割线的长度是这样的: 而QQ里面分割线左端到昵称的下面就截止了: 只需行代码就可以搞定: self.tableView.separatorInset = UIEdg ...
- C# 操作NPOI导入导出
//把T_Seats中的输入导出到Excel private void button3_Click(object sender, EventArgs e) { //1.读取 string sql = ...