- 浏览: 667238 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
lizaochengwen:
网络请求碰到的中文乱码使用encodeURL吧- (NSStr ...
iPhone开发/iPad开发 中文乱码问题 -
hhb19900618:
还是没弄懂怎么解决了中文乱码? 正确代码能重写贴出吗
iPhone开发/iPad开发 中文乱码问题 -
zhengjj_2009:
我的理解是讲ipa文件解压缩之后再重新打包,已经破坏了签名,所 ...
xcodebuild和xcrun实现自动打包iOS应用程序 -
zhengjj_2009:
我参考你的“ 从ipa格式的母包生成其它渠道包的shell脚本 ...
xcodebuild和xcrun实现自动打包iOS应用程序 -
同一片天空:
问题果然解决了
iOS 搭建 XMPP实现环境
本文由YoungShook原创,转载务必在明显处注明:http://blog.csdn.net/youngshook
前段时间和工作室的朋友一起协作开发了一款iOS平台上的软件,在软件完工之时,通过Instruments测试Leak,发现内存泄露严重,在解决了软件内存泄露之后,通过Instruments测试,内存泄露问题解决,特把一些管理内存的一些方法和网上常见的内存泄露解决方式分享给大家,为了不使本篇文章显的累赘繁杂,我特把分为四部分,也是我们常见的四种内存解决问题。
一、IOS内存管理的机制(没有使用ARC情况)
IOS中没有垃圾回收机制(IOS5中好像已经有了,但是目前还不太实用),所以基本一切都是自己手动管理。
IOS中采用引用计数的内存管理方式,啥意思呢?讲的通俗点就是说一块内存地址是否应该被释放是又retaincount来决定的,如果这块内存地址的retaincount为0,那么这块内存就会被释放,再也找不到了。
所以想让他一直存在,那么它的retaincount就必须大于0。
那么如何管理呢?其实原理非常简单,就是谁用谁retain,谁retain的谁release,遵循这个原则的目的就是让你不会出错。
举个例子
ClassA *obj1 = [[ClassA alloc] init];
复制代码
这里你申请了一块内存地址,指针obj1指向了这块内存地址,同时你给它retain了一下(retain,copy,alloc这几个方法都相当于把retaincount加一),此时obj1所指向的这块内存地址retaincount为1。
接着来(这里我只是举例子让大家了解一下,这些代码没有什么实际意义)
ClassA *obj2=obj1;
[obj2 retain];
复制代码
好了,大家看一下,obj1和obj2同时都指向了上面所述的内存地址,我假设这块内存为A,那么A这块内存的retaincount为2。
假如大家在之后一直在使用obj1和obj2,最后不用的时候,需要释放了,我希望大家这样来释放
[obj1 release];
[obj2 release];
复制代码
而不希望大家这样来释放
[obj1 release];
[obj1 release];
//或者
[obj2 release];
[obj2 release];
复制代码
为什么这样呢?上面两种释放方法没有错,都成功将A这块内存的retaincount减为0,导致A被释放了。但是你没有遵循以上所说“谁用谁retain,谁retain的谁release”。
这只是一个小例子,你可能感觉不到问题的严重性,如果你做一个项目,在其中有大量这种retain,release的话,你不遵循这种原则,你会死的很惨,没有条理最后你会被搞的很乱,找都找不到。
二、不要随便看到retaincount多就给它释放
很多朋友在学完内存管理后喜欢玩消除,不该释放的他去释放,举个例子
UIViewController *ct1=[[UIViewController alloc] init];
[self.navigationcontroller pushViewController:ct1 animated:YES];
[ct1 relese];
复制代码
这里,初始化一个viewcontroller,然后用导航push进来,最后释放这个viewcontroller,很多人在这里操作完毕后,继续打印ct1的retaincount,发现它的retaincount不为0,就继续release,这里是非常错误的方法,直接导致程序崩溃,继续看以上原则“谁用谁retain,谁retain的谁release”,你用的时候,初始化,并retain了一次,最后你release了一次,到此结束!之后不管你发现它的retaincount为几,你都不该再release。你打印出来的retaincount并不是你retain的,而是系统框架本身retain的,由框架本身来处理,开发者不必理会。
类似还有很多,数组的addobject、addsubview等等很多方法,都是框架自己家retain的,开发者本身retain后release,不必理会它的retaincount。
另外插一句,如果是多人协同开发,这种情况最容易碰到,别人传递一个参数过来,你拿过来retain后使用,使用完毕release,发现retaincount还不是0,于是你继续release,这样你就把你同伴retain的计数给release掉了,当他下次使用的时候发现崩溃了,这种情况会让你的团队浪费无数的时间来找原因。
三、关于属性
属性在.h文件中是这样声明的
@property(nonatomic,retain) Class *obj;
复制代码
括号内第二个参数代表的意义是什么呢?
我们分析一下他内部的机制
@property (retain) Class* obj;和@synthesize obj;实际上是getter和setter,有retain参数的property,内部代码如下
-(Class *) getObj
{
return obj;
}
-(void) setObj:(Class *) value
{
if (obj != value)
{
[obj release];
obj = [value retain];
}
}
复制代码
愿意仔细分析的童鞋可以仔细研究一下,不太明朗的童鞋请听我说。
这个属性定义以后如何使用呢?我们只说赋值(也就是set)
self.obj=xxx;
[self setObj:xxx];
obj=xxx;
赋值方法有以下几种,其中前两个是相同的,都是调用了setObj:方法同时也就导致了obj的retaincount增加了1,而第三个赋值方法并没有增加retaincount,只是将指针指向了xxx内存地址。
所以大家赋值时可以这样
Class *c=[[Class alloc] init];
self.obj=c;[c release];
或者Class *c=[[Class alloc] init];
[self setObj:c];[c release];
或者Class *c=[[Class alloc] init];obj=c;
复制代码
属性的这个机制是让你在整个self里(也就是当前类的实例里)一直保留这个obj的retaincount,所以你必须在此类的dealloc里将obj的retaincount置零(你只需要release,如果你严格遵守“谁用谁retain,谁retain的谁release”的话)
-(void)dealloc
{
[obj release];
[super dealloc];
}
复制代码
这里,其实我主要要说明的就是属性的赋值方式用self.xxx=xxxx和xxx=xxxx是完全不同的赋值方式,大家切记!
四、autorelease对象
autorelease对象就是自动释放对象,大家可能会疑惑,能自动释放,我还管理干嘛,我都用自动释放算了,事实不是这样的,自动释放确实好用,但是自己管理内存才能让项目占用更小的资源,跑起来更流畅,大家可以手动管理加autorelease一起来使用,我先讲解一下autorelease对象到底是什么个情况。
首先,告诉大家autorelease对象什么时候才会被释放。
在main函数里有一个autorelease pool,自动释放池,所以在这个自动释放池里的autorelease对象都会在自动释放池结束的时候全部被释放。
大家可能会问了,“难道所有的autorelease对象都是在程序退出的时候才被释放?”,答案当然不是,其实main函数中只是一个程序中众多自动释放池中的一个,每个runloop都会隐性的创建一个自动释放池,啥是一个runloop?每个UIView创建、delegate回调等等都会创建一个自动释放池,记得这个“等等”,意思就是有很多(如果大家想要详细了解runloop,可以去google)。所以大家不用担心autorelease对象不会被释放。
很多系统的方法,比如[NSArray array]、[NSString stringformat]等等返回的对象都是autorelease对象,这些对象是不需要手动释放的,如果手动释放会导致程序崩溃!切记!,原则就是系统中所有没有使用alloc、copy、retain来创建的对象都是autorelease对象,大家千万别手动release!
前段时间和工作室的朋友一起协作开发了一款iOS平台上的软件,在软件完工之时,通过Instruments测试Leak,发现内存泄露严重,在解决了软件内存泄露之后,通过Instruments测试,内存泄露问题解决,特把一些管理内存的一些方法和网上常见的内存泄露解决方式分享给大家,为了不使本篇文章显的累赘繁杂,我特把分为四部分,也是我们常见的四种内存解决问题。
一、IOS内存管理的机制(没有使用ARC情况)
IOS中没有垃圾回收机制(IOS5中好像已经有了,但是目前还不太实用),所以基本一切都是自己手动管理。
IOS中采用引用计数的内存管理方式,啥意思呢?讲的通俗点就是说一块内存地址是否应该被释放是又retaincount来决定的,如果这块内存地址的retaincount为0,那么这块内存就会被释放,再也找不到了。
所以想让他一直存在,那么它的retaincount就必须大于0。
那么如何管理呢?其实原理非常简单,就是谁用谁retain,谁retain的谁release,遵循这个原则的目的就是让你不会出错。
举个例子
ClassA *obj1 = [[ClassA alloc] init];
复制代码
这里你申请了一块内存地址,指针obj1指向了这块内存地址,同时你给它retain了一下(retain,copy,alloc这几个方法都相当于把retaincount加一),此时obj1所指向的这块内存地址retaincount为1。
接着来(这里我只是举例子让大家了解一下,这些代码没有什么实际意义)
ClassA *obj2=obj1;
[obj2 retain];
复制代码
好了,大家看一下,obj1和obj2同时都指向了上面所述的内存地址,我假设这块内存为A,那么A这块内存的retaincount为2。
假如大家在之后一直在使用obj1和obj2,最后不用的时候,需要释放了,我希望大家这样来释放
[obj1 release];
[obj2 release];
复制代码
而不希望大家这样来释放
[obj1 release];
[obj1 release];
//或者
[obj2 release];
[obj2 release];
复制代码
为什么这样呢?上面两种释放方法没有错,都成功将A这块内存的retaincount减为0,导致A被释放了。但是你没有遵循以上所说“谁用谁retain,谁retain的谁release”。
这只是一个小例子,你可能感觉不到问题的严重性,如果你做一个项目,在其中有大量这种retain,release的话,你不遵循这种原则,你会死的很惨,没有条理最后你会被搞的很乱,找都找不到。
二、不要随便看到retaincount多就给它释放
很多朋友在学完内存管理后喜欢玩消除,不该释放的他去释放,举个例子
UIViewController *ct1=[[UIViewController alloc] init];
[self.navigationcontroller pushViewController:ct1 animated:YES];
[ct1 relese];
复制代码
这里,初始化一个viewcontroller,然后用导航push进来,最后释放这个viewcontroller,很多人在这里操作完毕后,继续打印ct1的retaincount,发现它的retaincount不为0,就继续release,这里是非常错误的方法,直接导致程序崩溃,继续看以上原则“谁用谁retain,谁retain的谁release”,你用的时候,初始化,并retain了一次,最后你release了一次,到此结束!之后不管你发现它的retaincount为几,你都不该再release。你打印出来的retaincount并不是你retain的,而是系统框架本身retain的,由框架本身来处理,开发者不必理会。
类似还有很多,数组的addobject、addsubview等等很多方法,都是框架自己家retain的,开发者本身retain后release,不必理会它的retaincount。
另外插一句,如果是多人协同开发,这种情况最容易碰到,别人传递一个参数过来,你拿过来retain后使用,使用完毕release,发现retaincount还不是0,于是你继续release,这样你就把你同伴retain的计数给release掉了,当他下次使用的时候发现崩溃了,这种情况会让你的团队浪费无数的时间来找原因。
三、关于属性
属性在.h文件中是这样声明的
@property(nonatomic,retain) Class *obj;
复制代码
括号内第二个参数代表的意义是什么呢?
我们分析一下他内部的机制
@property (retain) Class* obj;和@synthesize obj;实际上是getter和setter,有retain参数的property,内部代码如下
-(Class *) getObj
{
return obj;
}
-(void) setObj:(Class *) value
{
if (obj != value)
{
[obj release];
obj = [value retain];
}
}
复制代码
愿意仔细分析的童鞋可以仔细研究一下,不太明朗的童鞋请听我说。
这个属性定义以后如何使用呢?我们只说赋值(也就是set)
self.obj=xxx;
[self setObj:xxx];
obj=xxx;
赋值方法有以下几种,其中前两个是相同的,都是调用了setObj:方法同时也就导致了obj的retaincount增加了1,而第三个赋值方法并没有增加retaincount,只是将指针指向了xxx内存地址。
所以大家赋值时可以这样
Class *c=[[Class alloc] init];
self.obj=c;[c release];
或者Class *c=[[Class alloc] init];
[self setObj:c];[c release];
或者Class *c=[[Class alloc] init];obj=c;
复制代码
属性的这个机制是让你在整个self里(也就是当前类的实例里)一直保留这个obj的retaincount,所以你必须在此类的dealloc里将obj的retaincount置零(你只需要release,如果你严格遵守“谁用谁retain,谁retain的谁release”的话)
-(void)dealloc
{
[obj release];
[super dealloc];
}
复制代码
这里,其实我主要要说明的就是属性的赋值方式用self.xxx=xxxx和xxx=xxxx是完全不同的赋值方式,大家切记!
四、autorelease对象
autorelease对象就是自动释放对象,大家可能会疑惑,能自动释放,我还管理干嘛,我都用自动释放算了,事实不是这样的,自动释放确实好用,但是自己管理内存才能让项目占用更小的资源,跑起来更流畅,大家可以手动管理加autorelease一起来使用,我先讲解一下autorelease对象到底是什么个情况。
首先,告诉大家autorelease对象什么时候才会被释放。
在main函数里有一个autorelease pool,自动释放池,所以在这个自动释放池里的autorelease对象都会在自动释放池结束的时候全部被释放。
大家可能会问了,“难道所有的autorelease对象都是在程序退出的时候才被释放?”,答案当然不是,其实main函数中只是一个程序中众多自动释放池中的一个,每个runloop都会隐性的创建一个自动释放池,啥是一个runloop?每个UIView创建、delegate回调等等都会创建一个自动释放池,记得这个“等等”,意思就是有很多(如果大家想要详细了解runloop,可以去google)。所以大家不用担心autorelease对象不会被释放。
很多系统的方法,比如[NSArray array]、[NSString stringformat]等等返回的对象都是autorelease对象,这些对象是不需要手动释放的,如果手动释放会导致程序崩溃!切记!,原则就是系统中所有没有使用alloc、copy、retain来创建的对象都是autorelease对象,大家千万别手动release!
发表评论
-
SOCK_STREAM和SOCK_DGRAM
2015-07-23 20:08 1672sock_stream 是有保障的(即能保证数据正确传送到 ... -
SOCKET bind INADDR_LOOPBACK和INADDR_ANY的区别
2015-07-23 19:49 2071今天写程序时候,服务器端启动了,然后客户端总是连接不上,con ... -
htons()
2015-07-23 19:26 597在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺 ... -
使用symbolicatecrash分析crash文件
2015-03-10 11:32 1193原文 http://www.cnblogs.com/ning ... -
程序设计中的计算复用(Computational Reuse)
2015-02-10 10:18 717从斐波那契数列说起 ... -
didReceiveMemoryWarning
2015-02-09 16:11 552IPhone下每个app可用的内存是被限制的,如果一个app使 ... -
iOS开发中怎么响应内存警告
2015-02-09 16:08 666好的应用应该在系统内存警告情况下释放一些可以重新创建的资源。在 ... -
ASIHTTPRequest多次重复请求的问题
2014-12-17 14:34 657在一个车票订购的项目中,点击一次订购,却生成了2次订单,通过抓 ... -
从 CloudKit 看 BaaS 服务的趋势
2014-09-26 11:51 739从 6 月份 WWDC 苹果发布 ... -
ios编程--AVCapture编程理解
2014-09-26 11:03 9690、媒体采集的几个东西。这里所需要明白的是,在这个流程中,这里 ... -
NSURLProtocol
2014-09-25 10:42 8401、http://nshipster.com/nsurlpro ... -
关于iOS8的extension插件
2014-09-25 10:41 1315关于iOS8的extension插件,有兴趣的同学可以参考一下 ... -
【转】ios app在itunesConnect里面的几种状态
2014-08-05 10:34 1170Waiting for Upload (Yellow) Ap ... -
[转]iOS Dev (45) iOS图标与切片处理工具Prepo
2014-02-07 17:02 1045iOS Dev (45) iOS图标与切片处理工具Prepo ... -
phoneGap开发IOS,JS调用IOS方法/phoneGap插件开发
2014-01-13 17:49 1254前沿 废话不说phoneGap是什么不多介绍,官方网站: h ... -
如何在IOS平台下搭建PhoneGap开发环境(PhoneGap2.5)
2014-01-13 15:23 763由于在下最近在做基于HTML5的跨平台移植,搭建环境的时候着实 ... -
xcode 4 制作静态库详解
2013-12-20 18:27 577最近在做Apple的IOS开发,有开发静态库的需求,本身IOS ... -
【翻译】ios教程-创建静态库
2013-12-20 18:19 3144作者:shede333 主页:htt ... -
封装自己的控件库:iPhone静态库的应用
2013-12-20 17:03 608由于iPhone 控件的极度匮乏和自定义组件在重用上的限制,在 ... -
iphone:使用NSFileManager取得目录下所有文件(遍历所有文件)
2013-11-18 17:56 889From:http://note.sdo.com/u/xiao ...
相关推荐
《iPhone游戏开发实践指南》是一本深入探讨iPhone游戏开发的专业书籍,它涵盖了从基础到高级的游戏开发技术。这本书的源代码提供了丰富的实例,帮助开发者更好地理解游戏开发过程中的各种概念和技巧。通过阅读和分析...
iPhone应用开发中的Object-C内存管理是开发者必须掌握的关键技能,特别是在资源有限的移动设备上,如iPhone OS(现称为iOS)。内存管理不当可能导致程序崩溃,严重影响用户体验。Object-C的内存管理基于引用计数机制...
《iPhone开发官方指南:内存管理编程指南》深入探讨了Objective-C环境下内存管理的关键原则和实践,特别是针对iOS平台的特定要求。 #### 内存管理概述 内存管理的核心在于有效地创建、使用和销毁对象,避免内存...
### IT知识点解析:《谢伟-基于iPhone...综上所述,《谢伟-基于iPhone开发实践》PDF不仅涵盖了iPhone开发的基本知识和技术要点,还深入探讨了移动应用开发中的常见问题及其解决方案,为开发者提供了宝贵的经验和指导。
### 基于iPhone开发实践 #### 演讲者简介 本次分享由博看文思CTO谢伟(Wayne)主讲。谢伟是一位热爱编程的技术专家,他在iPhone开发领域有着丰富的经验和深刻的见解。 #### 博看科技介绍 博看科技是一家专注于3G...
《iPhone游戏开发实践指南》是一本面向初学者和中级开发者的技术书籍,旨在通过实例和详细的指导,帮助读者掌握iOS平台上游戏开发的核心技能。配套源代码是本书教学内容的重要组成部分,它包含了书中各个章节实例的...
IOS IPhone 内存管理是指在 iPhone 和 Mac 中使用 Objective-C 语言管理内存的机制。该机制不同于 .Net/Java那种全自动的垃圾回收机制,而是基于 C 语言的手动管理方式,但添加了一些自动方法。下面是对 IOS IPhone ...
### iPhone内存管理:Objective-C中的深入解析 在iOS开发领域,内存管理是...通过本文的介绍,希望读者能够更加深刻地理解iPhone开发中内存管理的重要性,并能在实际项目中灵活运用这些知识,构建出高性能的应用程序。
ios iphone开发-内存管理 所有权是iPhone内存管理的核心思想,对象的所有者负责在使用完对象后进行释放。一个对象可以有多个所有者,当它没有所有者时将被设置为取消分配(deallocation)
4. **监控内存使用情况**:使用工具如Instruments来监控应用的内存使用,及时发现和解决潜在的内存问题。 ### 性能与内存管理 内存管理不仅关乎代码的健壮性,也直接影响应用的性能。过度的内存分配和释放会导致...
由于所提供的【部分内容】中重复的网址信息较多,且无实质性内容,因此这里重点对标题“iPhone游戏开发实践指南”和【描述】中提及的iPhone游戏开发相关知识点进行详细说明。 ### 知识点概述: #### 1. iPhone与...
在“iPhone开发实践”这一主题中,我们主要探讨的是如何针对iPhone平台进行应用开发,特别是基于Web的应用程序。iPhone开发基础教程通常涵盖了一系列的技术和工具,包括HTML、CSS、JavaScript,有时还会涉及PHP等...
### iPhone开发教程之iPhone内存释放注意事项两则 #### 内存管理基础知识 在iOS开发过程中,内存管理是一项非常重要的任务。对于iOS应用来说,如果内存管理不当,可能会导致程序崩溃或者被系统强制关闭。在...
iPhone游戏开发实践指南 中文版本 电子书 带完整书签
这本书也写得非常好,里面非常系统地讲解了开发iphone和ipad上面的游戏需要注意的一些问题,比如内存很少的问题等。同时书里还涉及了cocos2d开发中大部分的内容,基本上可以说是所有的内容。同时,这本书的作者的...
### iPhone创意开发入门与实践总结 #### 一、iPhone OS概览 iPhone OS是一个专为苹果公司的iPhone和iPod touch设备设计的操作系统。它由两个主要部分构成:一是操作系统本身,二是能够在这些设备上运行原生应用...
在iPhone开发的过程中,创意是核心,而良好的创意需要满足几个关键条件:解决问题、定位特定市场、提供娱乐性、改进现有应用以及具有优秀的用户体验。以下是对这些关键知识点的详细解释: 1. **创意的评估**: - *...
对于学习iPhone游戏开发,掌握C/C++是非常有益的,尤其是指针和内存管理这部分。这是因为Objective-C虽然在语法上有面向对象的封装,但它本质上仍是C语言的衍生,保留了指针和内存管理等底层特性。因此,对于初学者...
【正文】 《iPhone内存管理详解》 Objective-C作为iOS应用开发的主要编程语言,其内存管理机制对于开发者来说至关重要。...实践中,结合使用ARC和手动内存管理策略,可以在提高开发效率的同时,保证代码质量。