内存管理

内存在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...

 
}
}

以上是本篇文章的全部内容,欢迎指正和讨论。转载注明出处~

再谈内存管理与ARC运行机制(一)的更多相关文章

  1. OC的内存管理(二)ARC

    指针: 指向内存的地址指针变量 存放地址的变量指针变量值 变量中存放的值(地址值)指针变量指向的内存单元值 内存地址指向的值1):强指针:默认的情况下,所有的指针都是强指针,关键字strong ):弱 ...

  2. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  3. V8 内存管理和垃圾回收机制总结

    这篇文章主要介绍 V8 的内存管理和垃圾回收知识. V8 内存管理及垃圾回收机制浅析 由于 V8 引擎的原因,Node 在操作大内存对象时受到了一些限制,在 64 位的机器上,默认最大操作的对象大小约 ...

  4. [转载]再谈PostgreSQL的膨胀和vacuum机制及最佳实践

    本文转载自 www.postgres.cn 下的文章: 再谈PostgreSQL的膨胀和vacuum机制及最佳实践http://www.postgres.cn/news/viewone/1/390 还 ...

  5. C学习笔记(11)--- 可变参数,浅谈内存管理 【C基础概念系列完结】

    1.可变参数(variable arguments): 可变参数允许您定义一个函数,能根据具体的需求接受可变数量的参数. int func(int, ... )             (函数 fun ...

  6. JVM内存管理和垃圾回收机制介绍

    http://backend.blog.163.com/blog/static/20229412620128233285220/     内存管理和垃圾回收机制是JVM最核心的两个组成部分,对其内部实 ...

  7. JVM的生命周期、体系结构、内存管理和垃圾回收机制

    一.JVM的生命周期 JVM实例:一个独立运行的java程序,是进程级别 JVM执行引擎:用户运行程序的线程,是JVM实例的一部分 JVM实例的诞生 当启动一个java程序时.一个JVM实例就诞生了, ...

  8. 内存管理、ARC

    内存管理 一.基本原理 1.什么是内存管理 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间.比如回收一 ...

  9. java基础(一):谈谈java内存管理与垃圾回收机制

    看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...

随机推荐

  1. POJ 1699 Best Sequence dfs

    题目: http://poj.org/problem?id=1699 无意间A了..超时一次,加了一句 if(len > ans)return; 然后就A了,dfs题,没有太多好说的,代码写的效 ...

  2. Eclipse中的add jars和add external jars有什么区别(转载)

    转载自:http://blog.csdn.net/yasi_xi/article/details/12772457 add jars和add external jars有什么区别?   add ext ...

  3. 【ASP.NET】从服务器端注册客户端脚本

    一.在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArray ...

  4. CSS禅意

    标题取自<css禅意花园>一书,还记得当年读此书时的情景,真的是内容和书名一样的优秀,就以此标题作为自己在该文的一种追求吧,尽管我的水平和见解都和Dave Shea相去甚远.该文算是对前两 ...

  5. 【UVA 11354】 Bond (最小瓶颈生成树、树上倍增)

    [题意] n个点m条边的图 q次询问 找到一条从s到t的一条边 使所有边的最大危险系数最小 InputThere will be at most 5 cases in the input file.T ...

  6. php中header函数后是否应该有exit

    通常有一下三种:  代码如下 复制代码 Location: xxxx:yyyy/zzzz Content-Type: xxxx/yyyy Status: nnn xxxxxx 常用实例 1.实现重定向 ...

  7. 2.6.1 使用toast显示提示信息框

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout ...

  8. When to use DataContract and DataMember attributes?

    When to use DataContract and DataMember attributes? I  am very confused about the DataContract attri ...

  9. Scala:(3)数组

    要点: (1)长度固定使用Array,长度变化的则使用ArrayBuffer. (2)提供初始值时,不使用new. (3)用()访问元素 val a= new Array[String](10)//初 ...

  10. 如何删除MyEclipse(eclipse)中不需要的workspace

    在安装目录下,打开eclipse/configuration/.settings,用记事本打开org.eclipse.ui.ide.prefs文件 #Wed Mar 11 14:41:21 CST 2 ...