内存管理
内存在Objective-C开发中是一种相对稀缺的资源,拿Iphone4为例,它的内存只有512mb,所以妥善的处理好所创造,所使用的每个对象与变量都将成为一个问题。在ARC出现以前,同大部分基于C的编程语言一样,程序员需要考虑如何高效的管理内存。像在Java或是一些脚本语言中就不需要考虑内存管理的问题。
生命周期
Obj-c对象的创建,存活和销毁整个过程为它的声明周期。销毁后就会回收对象占用的内存。那么跟踪对象的使用,以及理解在什么时候释放资源十分重要。
看到这样一个问题,问为什么不在dealloc中release viewController而是立即释放呢?
MainViewController *viewController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
self.mainViewController = viewController;
[viewController release];
其实理解了持有者的作用就能很快回答,指针viewController在这里只是负责一个MainViewController的创建,以及给mainViewController传值的一个作用,之后它的存在并没有意义了,所以立即release掉来消除引用。
在频繁的增加持有者的时候,可以用retainCount属性来跟踪持有者的个数,当然在一些难以确定的区域,也可以借助autorelease来帮助管理。
内存管理好比于保安开和锁住大门。当人要进入公司工作时,先要打卡声明来工作了,走的时候也打卡说明下班了,当所有人都走了之后,保安才能锁住大门,提前锁或不锁都会出现一些问题。
一般来讲,内存管理遵循一些原则:
1.自己生成的对象,自己持有它(生成并持有的方法一般为:alloc,new,copy,mutableCopy)
2.不是自己生成的对象,自己也能持有
3.不再需要自己持有的对象,立即释放
4.不能释放不是自己持有的对象
内部实现
因为苹果公司不开源的原因,很多研究只能去看GNUstep来说明,GNUstep是Cocoa框架的互换框架。虽然不是完全相同,但从实现来说,应该是十分相近的。
+ alloc方法
alloc方法调用 +allocWithZone:
+ (id)allocWithZone:(NSZone *)z
{
return NSAllocateObject(self, 0, z); //这个方法负责分配内存空间并返回作为对象使用的id类型。
}
那么引用计数呢?
引用计数其实也是保存在一个结构体
struct obj_layout {
NSUInteger retained;
};
alloc类方法用这个结构体来保存引用计数并将其保存在头部,每调用一次alloc,指向结构体的指针给retained + 1。
那么访问retained的方法自然就去访问对象指针的头部
return ((struct obj_layout *) anObject)[-1].retained + 1; //anObject为传入的参数,理解为调用者本身(self)
那么,retain方法就会使上面的retained值自增1,release方法减1。
dealloc时,
struct obj_layout *o = &((struct obj_layout *) anObject)[-1];
free(o);
来废弃该结构体。
在《Objective-c 高级编程》中,作者给出了对苹果实现的猜测。大体思想还是类似的,不过存储方式貌似发生了改变,上面是将引用计数存储在了对象内存块的头部,而苹果实现,将其保存在了引用计数表的记录中。并且各自的好处如下:
头部管理:
少量代码即可完成。
能够统一管理引用计数用的内存块与对象用的内存块。
引用计数表管理:
对象用内存块的分配无需考虑内存块头部。
引用计数表各记录中存有内存块地址,可从各个记录追溯到各对象的内存块。
autorelease
经过autorelease的对象,不需要由我们手动去管理内存,而是由自动释放池(Autoreleasepool)来进行管理。尽管如此,只要不废弃AutoreleasePool对象,那么生成的对象就不能被释放,有时可能会产生内存不足的现象。所以要注意释放池的使用。
来看一下GNUstep对autorelease的实现
- (id)autorelease
{
[NSAutoreleasePool addObject:self];
}
在NSAutoreleasePool中对addObject:方法的实现
- (void)addObject:(id)anObj
{
[array addObject:anObj];
}
再来看下其他方法
- (void)drain
{
[self dealloc];
}
- (void)dealloc
{
[self emptyPool];
[array release];
}
- (void)emptyPool
{
for (id obj in array) {
[obj release];
}
}
那么,如果autorelease NSAutorelease对象会怎么样呢?
答案是肯定的,发生异常:不能自动释放一个自动释放池。
当然,自动释放池可以嵌套使用
@autorelease {
@autorelease {
code...
}
}
以上是本篇文章的全部内容,欢迎指正和讨论。转载注明出处~
分享到:
相关推荐
\ArcEngine开发——在64位操作系统下使用VS2010中开发ArcEngine应用程序的编译问题.
ArcEngine简单教程——栅格、矢量图层的颜色渲染对应demo; 备份链接:链接:https://pan.baidu.com/s/1e9I07SEFI1kRzmZuiLxQ7w 提取码:kkw5 教程博客:https://blog.csdn.net/nominior/article/details/106279762
iOS高级内存管理ARC模式手动模式英文文档含示例工程,本压缩包包含国外众多高手的内存管理心得和工程示例,文档为英文,不喜欢的请勿下载。
ArcEngine 10开发——许可问题,详细介绍ArcEngine 10开发中应该注意的许可问题。
ArcEngine简单教程——加载数据Demo,包括加载mxd、shp、grid、dat、img等数据 工程文件及测试数据 备份链接:链接:https://pan.baidu.com/s/14GoGMb88fagBGrkJloLpHQ 提取码:qfss 教程博客:...
ArcEngine简单教程——要素的属性查询、空间查询完整demo,包括要素图层的空间查询、属性查询 备份链接:链接:https://pan.baidu.com/s/1h5sRKIczpFErXhw4UPyLww 提取码:lw27 教程博客:...
ArcEngine简单教程——数据属性:属性表、识别(Identify);删除图层 等功能实现Demo。包括实现右击TOC可以显示数据属性表、删除图层,双击Map可以识别地图属性 备份连接:链接:...
OC内存管理:采用引用计数的方式管理内存 MRC :手动管理内存(手动管理引用计数) ARC:自动管理内存(自动管理引用计数)--系统默认
(2) 打开符号管理器,ArcScene——〉tools——〉styles——〉styles manager,弹出对话框: (3) 点击对话框右侧的“styles”按钮,选择“create new”项,创建你自己的符号库,保存在一定的路径下。创建好的...
这是一个简单的内存管理的示例,在非ARC的环境下,如何管理内存
arcengine内在图层创建(全)arcengine内在图层创建(全)arcengine内在图层创建(全)arcengine内在图层创建(全)
Objective-C提供了一系列的内存管理规则,包括MRC(Manual Reference Counting)中的`retain`、`release`和`autorelease`概念,以及在ARC(Automatic Reference Counting)中由编译器自动插入内存管理代码的机制。...
在objective-c中,内存的引用计数一直是一个让人比较...似乎ARC的出现只是让我们解放了双手,由于底层实现依然依赖引用计数,所以开启ARC后,只有对引用计数机制更加了解,才能避免Cycle Retain、Crash等问题的出现。
在ArcEngine中创建内存图层,版本是9.2,创建完操作和普通图层一样方便。
简单举例,步步检测,代码或有不好之处,还是有参考价值的。
Arc Hydro Tools流域提取方法应用——以辽宁省河流为例,康敏捷,栾维新,应用Arc Hydro Tools软件,以辽宁省为研究范围,采用目前分辨率较高的ASTER GDEM DEM数据,进行了辽宁省内河网及流域的提取。结果显示传统...
arcgis 9.3 license 2017年过期后 替换压缩包里面Arc_Info9.lic此文件即可,重启动arcgis license服务 ,亲测可用
从这里可以知道一些关于Xcode的内存管理,ARC模式下的内存管理
《Delphi Classic编译器和ARC编译器的内存管理》的代码示例图书目录及源代码