内存管理

内存在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. Leaflet学习笔记-基础内容

    为什么选择Leaflet 开源,且代码仅有 31 KB,但它具有开发人员开发在线地图的大部分功能(80%的功能) 是不是比arcgis要小很多呢 官网:http://leafletjs.com/ 劣势 ...

  2. Docker 安装jupyter notebook

    1. 利用image运行一个container sudo docker run -it --net=host tingting --net=host:让container可以上网,安装原来的sudo ...

  3. 关于在WIN32调用一些Zw系列的文件操作函数

    转自:http://blog.csdn.net/cooblily/archive/2007/10/27/1848037.aspx 都好久沒上來写文章了,都不知道做什么好,結果还是学写了一下用Nativ ...

  4. UNDO表空间损坏,爆满,ORA-600[4194]/[4193]错误解决

    模拟手工删除UNDO表空间 在ORADATA 中把UNDOTBS01.DBF 删除 模拟启库 SQL> STARUP; * 第 1 行出现错误: ORA-01157: 无法标识/锁定数据文件 2 ...

  5. WPF WebBroswer可以用到的接口

    http://pinvoke.net/default.aspx/Interfaces.DWebBrowserEvents2 [ComImport, SuppressUnmanagedCodeSecur ...

  6. BitMap 内存使用优化

    在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常.所以,对于图 ...

  7. POJ_3579_Median_(二分,查找第k大的值)

    描述 http://poj.org/problem?id=3579 给你一串数,共C(n,2)个差值(绝对值),求差值从大到小排序的中值,偶数向下取. Median Time Limit: 1000M ...

  8. Android开发学习笔记:浅谈WebView

    本文转自:http://www.2cto.com/kf/201108/101518.html WebView(网络视图)能加载显示网页,可以将其视为一个浏览器.它使用了WebKit渲染引擎加载显示网页 ...

  9. DBcontext应用于已存在数据库

    转自:http://www.cnblogs.com/Tally/archive/2013/01/30/2882855.html EF4.1有三种方式来进行数据操作及持久化.分别是Database-Fi ...

  10. devpress 很好的中文论坛

    阿伟邀请您访问DXPER开发者论坛http://www.dxper.net/?fromuid=3701