内存管理

内存在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. 黑马程序员-------.net基础知识二

    变量 变量代表着一块内存空间,我们可以通过变量名称想内存存/取数据,有变量就不需要我们记忆复杂的内存地址. 向内存中申请一块内存空间的语法:   数据类型 变量名; 变量类型 变量类型 存储位置 自动 ...

  2. android中监听layout布局

    android开发可以对layout文件夹中的xml文件里的布局进行监听,并处理事件,如:对RelativeLayout,LinearLayout,FrameLayout,GridLayout等布局容 ...

  3. 用Thread类创建线程-2

    支持原创,本系列文章均转自:http://www.blogjava.net/nokiaguy/category/38172.html 在Java中创建线程有两种方法:使用Thread类和使用Runna ...

  4. What is machine learning?

    What is machine learning? One area of technology that is helping improve the services that we use on ...

  5. Swift 中的静态方法继承

    Base and Derived Classes: class BaseClass{ class func staticMethod(){ println("BaseClass.static ...

  6. [wikioi]乌龟棋

    http://wikioi.com/problem/1068/ 多重背包.边界f[0,0,0,0]=a[1](初始时没有用任何卡片,获得棋盘第一格的分数)DP方程:f[i,j,k,l]=max(f[i ...

  7. 关于Team Leader

    他的生日3.16,结婚是在7月- 我感觉他领会整体架构方案的能力很强,几乎每次都能选择一个最优化的方案,比我这具体干活的想到更多更周全.但缺点是,不懂细活还是只能被下人拿捏.因为计算机环境那么复杂,每 ...

  8. listview异步加载sd卡图片

    package com.example.gridview; import java.io.File; import java.io.FileOutputStream; import java.io.I ...

  9. GCC优化选项-fomit-frame-pointer对于esp和ebp优化的作用

    我的博客:www.while0.com -fomit-frame-pointer选项是发布产品时经常会用到的优化选项,它可以优化汇编函数中用edp协助获取堆栈中函数参数的部分,不使用edp,而是通过计 ...

  10. perl use base 继承

    centos6.5:/root/podinns/lib#cat First.pm package First; use base qw(Second); sub new { my $self = {} ...