OBJECTIVE C内存管理教程和原理剖析

合集下载

好程序员特训营学习笔记ios内存问题

好程序员特训营学习笔记ios内存问题

Objective-C提供了三种内存管理方式:manual retain-release(MRR,手动管理),automatic reference counting(ARC,自动引用计数),garbage collection(垃圾回收)。

iOS不支持垃圾回收;ARC作为苹果新提供的技术,苹果推荐开发者使用ARC技术来管理内存;这篇笔记主要讲的是手动管理。

内存管理的目的是:1.不要释放或者覆盖还在使用的内存,这会引起程序崩溃;2.释放不再使用的内存,防止内存泄露。

iOS程序的内存资源是宝贵的。

MRR手动管理内存也是基于引用计数的,只是需要开发者发消息给某块内存(或者说是对象)来改变这块内存的引用计数以实现内存管理(ARC技术则是编译器代替开发者完成相应的工作)。

一块内存如果计数是零,也就是没有使用者(owner),那么objective-C的运行环境会自动回收这块内存。

objective-C的内存管理遵守下面这个简单的策略:注:文档中把引用计数加1的操作称为“拥有”(own,或者take ownership of)某块对象/内存;把引用计数减1的操作称为放弃(relinquish)这块对象/内存。

拥有对象时,你可以放心地读写或者返回对象;当对象被所有人放弃时,objective-C的运行环境会回收这个对象。

1.你拥有你创建的对象也就是说创建的对象(使用alloc,new,copy或者mutalbeCopy等方法)的初始引用计数是1。

2.给对象发送retain消息后,你拥有了这个对象3.当你不需要使用该对象时,发送release或者autorelease消息放弃这个对象4.不要对你不拥有的对象发送“放弃”的消息注:简单的赋值不会拥有某个对象。

比如:...NSString *name = ;...上面这个赋值操作不会拥有这个对象(这仅仅是个指针赋值操作);这和C++语言里的某些基于引用计数的类的行为是有区别的。

Objective-C内存管理教程和原理剖析

Objective-C内存管理教程和原理剖析
returnautorelasepoolcreatedcreateclassacreateautoreleaseclassbdestroyedmanuallyreleaseclassaclassadestroyed我们可以看出来我们并没有创建任何autoreleasepool可是classb实例依然被自动销毁了这说明新的runloop自动创建了一个autoreleasepool这个pool在新的runloop结束的时候会销毁自己并自动release所包含的对象
ClassA *obj2 = obj1; //retain count = 1
[obj2 retain]; //retain count = 2
[obj1 hello]; //输出 hello
//对于 obj1,无需调用(实际上不能调用)release
[obj2 hello]; //输出 hello
ClassA *obj2 = obj1;
[obj1 hello]; //输出 hello
[obj1 dealloc];
[obj2 hello]; //能够执行这一行和下一行吗?
[obj2 dealloc];
不能,因为 obj1 和 obj2 只是指针,它们指向同一个对象,[obj1 dealloc] 已经销毁这个对象了,不能再调用[obj2 hello]和[obj2 dealloc]。obj2 实际 上是个无效指针。
[loopPool release];
}
[pool release];
return (0);
} // main
(可以参考附件中的示例程序 memman-many-objs-many-pools.m,占用内存 的变化极小)
二 口诀与范式

Objective-C 2.0之前需要了解的:关于Obj-C内存管理的规则

Objective-C 2.0之前需要了解的:关于Obj-C内存管理的规则

Objective-C 2.0之前需要了解的:关于Obj-C内存管理的规则/index.php/archives/cocoachina_110.htmlObjective-C 2.0增加了一些新的东西,包括属性和垃圾回收。

那么,我们在学习Objective-C 2.0之前,最好应该先了解,从前是什么样的,为什么Objective-C 2.0要增加这些支持。

这一切都跟Cocoa内存的管理规则有关系,我们知道,Objective-C中所有变量都定义为指针。

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址,如果使用不当,就会出错或者造成内存的泄露。

要了解这些,就需要看看其内存管理的规则到底是什么样的。

这篇文章也应该做为苹果开发工具中提供的性能调试工具Instruments使用前必读知识进行阅读。

Cocoa China将在稍后提供Instruments工具的使用方法,以及Objective-C 2.0的详细介绍。

要知道,如果你使用Objective-C 2.0,那么本文描述的大部分工作你都不需要自己去处理了。

但是这并不意味着你可以不了解它,相反,只有你对内存管理规则更加了解,你才能更好地使用Objective-C 2.0带来的便利。

本文原文作者是Mmalcolm Crawford,原文地址这篇文章翻译起来比较晦涩,希望您能看得懂。

当Cocoa新手在进行内存管理时,他们看上去总是把事情变得更为复杂。

遵循几个简单的规则就可以把生活变得更简单。

而不遵循这些规则,他们几乎一定会造成诸如内存泄露或者将消息发送给释放掉的对象而出现的的运行错误。

Cocoa不使用垃圾回收(当然,Objective-C 2.0之后开始就使用了),你必须通过计算reference的数量进行自己的内存管理,使用-retain, -release和-autorelease。

方法描述-retain将一个对象的reference数量增加1。

突破Objective-C开发速学手册之内存管理

突破Objective-C开发速学手册之内存管理

2.autorelease
#import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { NSString *str=[[[NSString alloc]init]autorelease]; ... return 0; } 在方法退出 前不会被释 放
9.4.2 内存泄露

当以前分配的一片内存不再需要使用或无 法访问时,但是却并没有释放它,那么对 于该进程来说,会因此导致总可用内存的 减少,这时就出现了内存泄漏。内存泄漏 指由于疏忽或错误造成程序未能释放已经 不再使用的内存的情况。
9.5 垃圾回收


垃圾回收(Garbage Collectionji简称GC)是 Objective-C提供的一种自动内存回收机制。它可以 让程序员减轻许多内存管理的负担,即无需再使用 release和autorelease。在程序的声明周期中,系统负 责自动回收没有引用或相连的对象所占用的内存, 这种内存回收的过程就叫垃圾回收。 Apple在OS10.5里追加了这个功能。首先我们先将 垃圾回收开启。单击项目文件,再选项卡中选择 “Build Settings”按钮,在按下“ALL”按钮,选 择“Apple LLVM compiler 3.0 Language”中的 “Objective-C Garbage Collection”选项,将其设置 改为“Unsuppored”选择。

所谓内存管理规则就是在内存中要遵守的 一系列规则,我们必须牢牢遵守,才不会 使资源遭到不必要的浪费。
1.使用规定的方法创建对象

当使用new()、alloc()、copy()方法创建一个 对象时,该对象的保留计数器值为1。当不 再使用该对象时,开发人员要负责向该对 象发送一条release或autorelease消息。这样, 该对象将在其使用寿命结束时被销毁。

学习Objective-C入门教程(全)

学习Objective-C入门教程(全)

学习Objective-C入门教程1,前言相信iPhone不久就要在国内发布了,和我们在国内可以通过正规渠道买得到的iPodTouch一样,iPhone也是一个激动人心的产品。

iPhone发布的同时,基于iPhone的程序也像雨后春笋一样在iTunes里面冒出来。

你将来也许会考虑买一个iPhone,体验一下苹果的富有创意的种种应用;你也许会考虑向iTunes的社区的全世界的人们展示一下你非凡的创意,当然也可以通过你的创意得到一些意想不到的收益。

OK,你也许迫不及待的准备开发了。

但是先等一下,让我们回忆一下最初的电影是怎么拍摄的。

这个很重要,因为和iPhone的开发比较类似。

在最初因为器材比较原始,所以拍摄电影需要很高的技术,那个时候的电影的导演基本上是可以熟练操作摄影器材的人。

随着器材的完善,使用也简单起来。

于是器材的使用不是决定一个电影的质量的唯一的因素,取而代之的是故事或者说电影的创意。

iPhone的开发也是这样。

当然从入门到掌握的过程来说任何事情都是开始比较难,随着掌握的程度的加深,你将会觉得开发iPhone应用程序是一件简单而且轻松的事情,到了那个时候,你的主要的制胜武器就不是开发技术,而是你的创意了。

对于你来说,我在这里写的东西都是有关“摄影器材”也就是介绍如何使用iPhone的平台来开发应用程序。

iPhone的开发语言是Objective-C。

Objective-C是进行iPhone开发的主要语言,掌握了Objective-C的基本语法以及数据结构之后,你需要熟悉一下iPhone的SDK。

笔者很难做到在一篇文章里面把所有的东西都介绍清楚,所以笔者打算分成两个主题,一个是Objective-C,一个是iPhone开发。

本系列将侧重于Objective-C。

当然,任何一种开发语言都无法脱离于运行环境,Objective-C也不例外。

所以在本系列当中也会穿插的介绍一些SDK里面的一些特性,主要是数据结构方面,比如说NSString,NSArray等等。

10 内存管理1

10 内存管理1

不能,因为str1和str2只是指针,它们指向同一个对象, [str1 dealloc]时,已经销毁这个对象了,此后,str2实际 上是个无效指针。
内存管理模型
手工引用计数和自劢释放池(也叫保留计
数,NSObject对此行为迚行了封装实现)
自劢垃圾回收(Java,MAC OS X 10.6 ObjectiveC2.0上均可支持,注意iOS开发不支持)
Objective-C程序设计
第10讲 内存管理1
目 录
1
内存管理相关概念
手工引用计数和自动释放池
2 3
3
自动垃圾回收
自动引用计数(ARC)
4 3
为何需要内存管理
计算机的资源是有限的,我们需要合理使用。试想 所有学生都到图书馆去借书而不归还,再多的图书 也会很快借光的。计算机的主要资源: 1、内存、显存;
使用NSLog记彔引用计数器的变化 重写init和dealloc方法
- (id) init{ if (self = [ ]) { NSLog (@"init: Retain count of %d.", [self retainCount]); } return (self); } // init - (void) dealloc{ NSLog (@"dealloc called. Bye Bye.");
Engine *myengine = [Engine new]; [car setEngine: myengine];
Car
(void) setEngine: (Engine *)newEngine{ engine=newEngine; }
set方法设计策略
保留释放法 ①在访问方法中,先保留新对象,即将形参对应对象 的保留计数器加1。 [形参 retain]; ②释放旧对象,即将实参对应对象的保留计数器减1。 [实参 release]; ③用形参对象给实参对象赋值。

简单讲解Objective-C的基本特性及其内存管理方式.

简单讲解Objective-C的基本特性及其内存管理方式.

简单讲解Objective-C的基本特性及其内存管理方式这篇文章主要介绍了简单讲解Objective-C的基本特性及其内存管理方式,虽然Swift语言出现后iOS和Mac OS应用开发方面Objective-C正在成为过去时,但现有诸多项目仍然在使用,需要的朋友可以参考下一、OC简介Oc语言在c语言的基础上,增加了一层最小的面向对象语法,完全兼容C语言,在OC代码中,可以混用c,甚至是c++代码。

可以使用OC开发mac osx平台和ios平台的应用程序。

拓展名:c语言-.c OC语言.-m 兼容C++.-mm注:其实c语言和oc甚至任何一门语言都只是我们为了实现一些功能,达到一些效果而采用的工具,抛开语法的差别外,我想最重要的应该是在解决问题的时候考虑的角度和方法不一样而已,然而这也构成了学习一门语言的重要性。

二、语法预览(1)关键字基本上所有的关键字都是以@开头的(为了与c语言的关键字区分开来),如@interface @implemen tation @public等,少部分没有以@开头,如id,_cmd等(2)字符串以@开头C语言字符串:“hello”OC语言字符串:@“hello”(3)其他语法基本类型:5种,增加了布尔类型Nil相当于是null,也就是0。

屏幕输出:NSLog(@“hello”);//自动换行NSLog(@“age is %d”,2);三、OC程序开发过程#import预处理指令有两个作用:(1)与#include一样,拷贝文件内容(2)可以自动防止文件的内容被重复拷贝程序编译连接过程:源文件(.m)---(编译)---->目标文件(.0)-----(链接)---->可执行文件(.out)Foundation框架。

如果要使用框架中的所有头文件那么应该怎么办?包含框架的主头文件。

主头文件是一个框架中最主要的头文件,每个框架的主头文件名和框架名一致。

如#import<foundation/foundation.h>运行过程如下:(1)编写OC源文件 .m .c(2)编译文件 cc -c xx.m xxx.c(3)链接 cc xx.o xxx.o -framework Foundation(4)运行 ./a.out四、类型补充复制代码代码如下:Int main(){BOOL b=YES;BOOL b1=NO;BOOL b2=1;// YESBOOL b3=2;// NONSLog(@“%i”,b);}BOOL类型与其他类型的用法一致,BOOL类型的本质是char类型的,定义如下:复制代码代码如下:Typedef signed char BOOL宏定义:复制代码代码如下:#define YES (BOOL)1#define NO (BOOL)0布尔类型的输出一般当做整数来用。

Objective-C 内存管理技巧与经验

Objective-C 内存管理技巧与经验
- (void) notifyUserOfError: (NSString *)errorString { NSMutableString *alertString = nil;
alertString = [[NSMutableString alloc] initWithString: @”The following error occurred: “]; [alertString appendString: errorString]; NSRunAlertPanel( alertString …); [alertString release];
2,对象持有制 (Object Ownership,不知道要翻译成啥,暂时叫他持有制,其实这个叫法本身就有些字面上的误导。 了解它的本质就OK了,不必太在意它叫什么。^_^)
基础类库与其它类库都推荐我们下面两个对象创建与销毁的策略: a 如果你创建了一个对象,你有责任把它销毁 b 如果你想持有一个并不是你创建的对象,你需要”retain”它,并在不需要时”release”掉
// Loop that creates many temporary objects while ( theObject == nil ) { … if ( [temporaryObject matchesSomeCondition] ) { theObject = [temporaryObject retain]; // We want this one } }
Objective-C 内存管理技巧与经验
在具备了基础的理论知识后,还需要些内存管理上的技巧与经验。这点由其对从JAVA类语言过来的程 序员,咱们实话实说,内存管理真不是咋们长项,更需要花更多的时间与精力来积累相关知识。不过话又 说回来,人都说做生意的都讲究吃亏在前赚钱在后。开始时候多卖点力,这座美丽的“金山”早晚是我们的。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[NSString stringWithFormat:@"1234567890"];//产生的对象是 autorelease 的。
[loopPool release]; } [pool release]; return (0); } // main (可以参考附件中的示例程序 memman-many-objs-many-pools.m,占用 内存的变化极小)
5.1 新生成的对象,只要调用 autorelease 就行了,无需再调用 release! ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 但无 需调用 release
5.2 对于存在指针赋值的情况,代码与前面类似。 ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 ClassA *obj2 = obj1; //retain count = 1 [obj2 retain]; //retain count = 2 [obj1 hello]; //输出 hello //对于 obj1,无需调用(实际上不能调用)release [obj2 hello]; //输出 hello [obj2 release]; //retain count = 2-1 = 1
2 Objective-C 的对象在使用完成之后不会自动销毁,需要执行 dealloc 来释放空 间(销毁),否则内存泄露。
[obj1 dealloc]; 这带来了一个问题。下面代码中 obj2 是否需要调用 dealloc?
ClassA *obj1 = [[ClassA alloc] init]; ClassA *obj2 = obj1; [obj1 hello]; //输出 hello [obj1 dealloc]; [obj2 hello]; //能够执行这一行和下一行吗? [obj2 dealloc];
6.4 默认只有一个 autorelease pool,通常类似于下面这个例子。 int main (int argc, const char *argv[]) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init];
]之后,obj2 依然是个无效指针。问题依然没有解决。解决方法见下
4 Objective-C 指针赋值时,retain count 不会自动增加,需要手动 retain。 ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1 ClassA *obj2 = obj1; //retain count = 1 [obj2 retain]; //retain count = 2 [obj1 hello]; //输出 hello [obj1 release]; //retain count = 2 – 1 = 1 [obj2 hello]; //输出 hello [obj2 release]; //retain count = 0,对象被销毁 问题解决!注意,如果没有调用[obj2 release],这个对象的 retain count 始终
int main (int argc, const char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int i, j; for (i = 0; i < 100; i++ )
{ NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; for (j = 0; j < 100000; j++ )
不能,因为 obj1 和 obj2 只是指针,它们指向同一个对象,[obj1 dealloc]已经销 毁这个对象了,不能再调用[obj2 hello]和[obj2 dealloc]。obj2 实际上是个无效指针。
如何避免无效指针?请看下一条。
3 Objective-C 采用了引用计数(ref count 或者 retain count)。对象的内部保存 一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的 retain count 为 2。需要销毁对象的时候,不直接调用 dealloc,而是调用 release。release 会 让 retain count 减 1,只有 retain count 等于 0,系统才会调用 dealloc 真正销毁这个对 象。
ClassA *obj1 = [[ClassA alloc] init]; //对象生成时,retain count = 1 [obj1 release]; //release 使 retain count 减 1,retain count = 0,dealloc 自 动被调用,对象被销毁 我们回头看看刚刚那个无效指针的问题,把 dealloc 改成 release 解决了吗? ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1 ClassA *obj2 = obj1; //retain count = 1 [obj1 hello]; //输出 hello [obj1 release]; //retain count = 0,对象被销毁 [obj2 hello]; [obj2 release];
6.3 NSAutoreleasePool 自身在销毁的时候,会遍历一遍这个数组, release 数组中的每个成员。如果此时数组中成员的 retain count 为 1,那么 release 之后,retain count 为 0,对象正式被销毁。如果此时数组中成员的 retain count 大于 1,那么 release 之后,retain count 大于 0,此对象依然没有被销毁,内存 泄露。
为 1,不会被销毁,内存泄露。(1-4 可以参考附件中的示例程序 memman-no-pool.m)
这样的确不会内存泄露,但似乎有点麻烦,有没有简单点的方法?见下一条。
5 Objective-C 中引入了 autorelease pool(自动释放对象池),在遵守一些规 则的情况下,可以自动释放对象。(autorelease pool 依然不是.Net/Java 那种全自动的 垃圾回收机制)
口诀与范式
1 口诀。 1.1 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过 alloc、new 或 copy 来 创建一个对象,那么你必须调用 release 或 autorelease。换句话说,不是你创建的, 就不用你去释放。 例如,你在一个函数中 alloc 生成了一个对象,且这个对象只在这个函数中被使用, 那么你必须在这个函数中调用 release 或 autorelease。如果你在一个 class 的某个方法 中 alloc 一个成员对象,且没有调用 autorelease,那么你需要在这个类的 dealloc 方法 中调用 release;如果调用了 autorelease,那么在 dealloc 方法中什么都不需要做。 1.2 除了 alloc、new 或 copy 之外的方法创建的对象都被声明了 autorelease。 1.3 谁 retain,谁 release。只要你调用了 retain,无论这个对象是如何生成的,你都要调 用 release。有时候你的代码中明明没有 retain,可是系统会在默认实现中加入 retain。 不知道为什么苹果公司的文档没有强调这个非常重要的一点,请参考范式 2.7 和第三 章。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 6.2 NSAutoreleasePool 内部包含一个数组(NSMutableArray),用来 保存声明为 autorelease 的所有对象。如果一个对象声明为 autorelease,系统所 做的工作就是把这个对象加入到这个数组中去。 ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1, 把此对象加入 autorelease pool 中
[pool release]; return (0); } // main 所有标记为 autorelease 的对象都只有在这个 pool 销毁时才被销毁。如果你有大 量的对象标记为 autorelease,这显然不能很好的利用内存,在 iphone 这种内存 受限的程序中是很容易造成内存不足的。例如: int main (int argc, const char *argv[]) {
细心的读者肯定能发现这个对象没有被销毁,何时销毁呢?谁去销毁它?(可以参考附件中 的示例程序 memman-with-pool.m)请看下一条。
6 autorelease pool 原理剖析。(其实很简单的,一定要坚持看下去,否则还是 不能理解 Objective-C 的内存管理机制。)
6.1 autorelease pool 不是天生的,需要手动创立。只不过在新建一个 iphone 项目时,xcode 会自动帮你写好。autorelease pool 的真名是 NSAutoreleasePool。
2 范式。 范式就是模板,就是依葫芦画瓢。由于不同人有不同的理解和习惯,我总结的范式不一定 适合所有人,但我能保证照着这样做不会出问题。 2.1 创建一个对象。 ClassA *obj1 = [[ClassA alloc] init]; 2.2 创建一个 autorelease 的对象。 ClassA *obj1 = [[[ClassA alloc] init] autorelease]; 2.3 Release 一个对象后,立即把指针清空。(顺便说一句,release 一个空指针是合法的, 但不会发生任何事情) [obj1 release]; obj1 = nil; 2.4 指针赋值给另一个指针。 ClassA *obj2 = obj1; [obj2 retain];
相关文档
最新文档