iOS 内存管理

1.内存管理原则(引用计数)

iOS的对象都继承于NSObject, 该对象有一个方法 :retainCount,内存引用计数。引用计数在很多计数都用到:window下的COM组件,多线程的信号量,读写锁,思想都一样。

alloc 对象分配后引用计数为1

retain 对象引用计数+1

copy copy一个对象变成新的对象(新内存地址)引用计数为1原来对象计数不变

release 对象引用计数-1 如果为0释放内存

autorelease 对象引用计数-1 如果为0不马上释放, 最近一个自动释放池释放

可以用以下方法打印引用计数

NSLog (@"a retainCount : %u", [a retainCount])

内存管理的原则就是最终的引用计数要平衡,

如果最后引用计数大于0 则会内存泄露

如果引用计数等于0还对该对象进行操作,则会出现内存访问失败,即crash 所以尽量设置为nil


2.autoReleasePool

每个工程都有一个main.m文件:内容如下:

int main(int argc, char *argv[]) {

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

int retVal = UIApplicationMain(argc, argv, nil, nil);

[pool release];

return retVal;

}

很明显C语言的main函数

NSAutoreleasePool是用来做autorelease变量释放的, 前面说了, autorelease不会马上释放, 当他到了最近的pool release 时 会检查retain count 是不是0, 为0就释放

当我们在一段代码时加入大量的autorelease 变量时,我们应该为这段代码加上 AutoreleasePool, 其他时候不用

在返回一个对象时常常像C/C++一样返回一个对象到栈, 只能用autorelease对象

3. 成员变量与属性

实际情况并非上面那么简单, 你可能需要在一个函数里调用另一个函数分配的变量这时候有两个选择: 类成员变量和使用属性

@interface TestMem:NSObject {

TestObject *m_testObject; // 成员变量

TestObject *testObject; // 成员变量

}

成员变量与上面的内存管理师一直的, 只是在不同的函数里要保持引用计数加减的平衡,所以要你要每次分配的时候检查是否上次已经分配了。 是否还能调用什么时候用属性?

1.把成员作为public.

2.outlet一般声明为属性(这个内存于系统控制,但我们还是应该做一样操作, 后面会讲)

3.如果很多函数都需要改变这个对象, 或这个函数会触发很多次, 建议使用属性。我们看看属性函数展开后是什么样子:

-(void)setTestObject:(id)newValue {

   testObject = newValue;

}

- (void)setTestObject:(id)newValue {

  if (testObject!= newValue) {

     [testObject release];

     testObject =  [newValue retain];

  }

}

- (void)setTestObject:(id)newValue {

   if (testObject != newValue) {

     [testObject release];

     testObjce = [newValue copy];

  }

}

assign 相当于指针赋值, 不对引用计数进行操作, 注意原对象不用了, 一定要把这个设置为nil

retain 相当于对原对象的引用计数改变,生成一个新对象引用计数为1

注意:

self.testObject 左值调用的是setTestObject 方法。右值为get方法,get方法比较简单不用说了 而真接testObject使用的是成员变量

self.testObject = [[testObject alloc] init]; // 错 retain 两次

testObject = [NSArray objectbyindex:0]; // 错 不安全,没有retain 后面release 会出错

4.自动管理对象

iOS 提供了很多static(+)创建对象的类方法, 这些方面是静态的,可以直接用类名调用如:

NSString *testString = [NSString stringWithFormat: @"test"];

testString 是自动管理对象, 你不用release他, 他有一个很大的 retain count, release后数字不变

5 .例外

 有一些通过alloc生成的对象相同是自动管理的如:

NSString *testString = [NSString stringWithFormat:@"test"];

retainCount 同样是很大的数, 没办法release

但为了代码对应, 还是应该加上[testString release];

不然xcode的Analyze 会认识内存leak, 但Instruments leak 工具检测是没有的

IPhone/Mac Objective-C内存管理教程和原理抛析

前言

初学Objective—C的朋友都有一个困惑, 总觉的对Objective-C的内存管理机制琢磨不透,程序经常内存泄露或莫名其妙崩溃。我在这里总结了自己对Object—C内存管理机制的研究成果和经验, 写了这么一个由浅入深的教程。希望对大家有所帮助, 也欢迎大家一起探讨。

一、基本原理

Objective-C的对象在使用完成之后不会自动销毁, 需要执行dealloc来释放空间(销毁), 否则内存泄露。

在此不在详述。

二、口诀与范式

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. 范式

范式就是模板, 几十照葫芦画瓢。 由于不同人有不同的理解和习惯, 我总结的范式不一定适合所有人, 但我能保证照着这样做不会出问题

2.1 创建一个对象

 ClassA *objc1 = [[ClassA class] init];

2.2 创建一个autorelease的对象

ClassA *obj1 = [[[ClassA alloc] init] autorelease];

2.3 Release一个对象后, 立即把指针清空。

  [objc1 release];

   obj1 = nil

三、系统自动创建新的autorelease pool

在生成新的Run Loop的时候, 系统会自动创建新的autorelease pool 。注意。此处不同于Xcode在新建项目时自动生成的代码中加入的autorelease pool。 Xcode 生成的代码可以被删除, 但是系统自动创建的新的autorelease pool是无法删除的(对于无Garbage Collection 的环境来说)。 Objective-C没有给出实现代码,官方文档也没有说明。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • 1. 内总管理原则(引用计数) IOS的对象都继承于NSObject, 该对象有一个方法:retainCount...
    lilinjianshu阅读 2,154评论 0 2
  • iOS目前已经是ARC 时代。但对于要想了解ARC的内存管理机制,还是依旧需要对MRC时代的内存管理机制有深刻的理...
    ivylee_mr阅读 1,748评论 0 2
  • 一、MRC(手动引用计数): 不像 java 有垃圾回收机制,Objective-C 继承于 C ,使用一套基于对...
    Lee坚武阅读 981评论 0 51
  • Objective-C提供了三种内存管理方式:manual retain-release(MRR,手动管理),au...
    挡不住的狮子阅读 201评论 0 0
  • # 前言 反复地复习iOS基础知识和原理,打磨知识体系是非常重要的,本篇就是重新温习iOS的内存管理。 内存管理是...
    Vein_阅读 790评论 0 2