内存管理题

2020-10-30  本文已影响0人  一个半吊子工程师

1.管理原则

1.1内存管理-黄金法则

The basic rule to apply is everything that increases the reference counter with alloc, [mutable]copy[withZone:] or retain is in charge of the corresponding [auto]release.

如果对一个对象使用了alloc、[mutable]copy、retain,那么你必须使用相应的release或者autorelease。

1.2类型定义:

基本类型:任何C的类型,如:int、short、char、long、struct、enum、union等属于基本类型或者结构体;

内存管理对于C语言基本类型无效;

任何继承与NSObject类的对象都属于OC类型。

所有OC对象都有一个计数器,保留着当前被引用的数量。

1.3内存管理对象:

OC的对象:凡是继承于NSObject;

每一个对象都有一个retainCount计数器。表示当前的被应用的计数。如果计数为0,那么就真正的释放这个对象。

alloc、retain、release函数:

1)alloc 函数是创建对象使用,创建完成后计数器为1;只用1次。

2)retain是对一个对象的计数器+1;可以调用多次。

3)release是对一个对象计数器-1;减到0对象就会从内存中释放。

增加对象计数器的三种方式:

1)当明确使用alloc方法来分配对象;

2)当明确使用copy[WithZone:]或者mutableCopy[WithZone:]copy对象的时;

3)当明确使用retain消息。

上述三种方法使得计数器增加,那么就需要使用[auto]release来明确释放对象,也就是递减计数器。

2. 非ARC模式,MRR(manual retain-release)

MRR内存管理里的一个核心原则,“只负责你拥有的对象的生命周期”,也就是说,如果你对一个对象有所有权,那么你就要负责其回收的工作,否则,你不需要,也不能取回收你不拥有的对象。

1:所有使用alloc, new, copy或mutabelCopy,以及这些关键词开头的函数返回的对象,你都是拥有所有权的,也就是要负责这些对象的内存回收工作。这是iOS开发中的一种约定,所以,当你编写自己的alloc, new或copy类型的函数时,也请遵循这样的命名规范。

2:retain返回的对象,拥有所有权。例如显示调用retain函数返回的结果,或者synthesize 的retain类型的成员变量。

3:所有使用其他函数返回的对象,没有所有权。

4:返回的对象的引用,没有所有权。

5:autorelease返回的对象没有所有权。

2.1 cocoa中的内存管理机制——引用计数

引用计数是实例对象的内存回收唯一参考
引用计数(retainCount)是Objective-C管理对象引用的唯一依据。调用实例的release方法后,此属性减一,减到为零时对象的dealloc方法被自动调用,进行内存回收操作,也就是说我们永不该手动调用对象的dealloc方法。
关于dealloc方法它的作用是,当对象的引用计数为0时,系统会自动调用dealloc方法,回收内存,它的一般写法为:


-(void)dealloc
{      
      [super  dealloc];
      [person release];                                                                                 
}        

在这里为什么要调用父类的dealloc方法呢?

2.2 对象所有权

当一个所有者(可以是任何一个OC对象)做了以下某个动作的时候,它就拥有了对一个对象的所有权。

//(1)如果创建或者复制某个对象时,则拥有了该对象的所有权,即包含下列关键词时:
alloc,allocWithZone:,copy,copyWithZone:,mutableCopy,mutableCopyWithZone:

//(2)如果没有创建或复制对象,而是保留引用,同样拥有该对象的使用权
 retain
//(3)当拥有了某个对象的所有权,在不需要某一个对象时,需要释放他们,用
 release,autoRelease

2.3 自动释放池的相关用法

1)cocoa中的自动释放池(Autorelease pool),是能够自动释放赤忠的对象的。NSObject类提供了一个autorelease消息,当我们想一个对象发送autorelease消息的时候,这个对象就会随着释放池的销毁而释放。如果要向使用使用自动释放池释放对象,我们首先要有一个入池操作:

 //入池对象5.0之后的写法
//创建自动释放池
@autoreleasepool {
    //入池对象5.0之后的写法
 }

//入池对象5.0之前写法
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[pool release];

自动释放池是以栈的形式实现的,当某个对象调用了autorelease方法时,该对象会被加入自动释放池的栈顶。对于发送了autorelease消息的对象,当自动释放池销毁时,自动释放池会对这些对象发送一条release消息,来释放他们。

2)向自动释放池发送release及drain消息的区别
当我们向自动释放池pool发送release消息时,它会向池中的每一个发送了autorelease消息的对象发送一条release消息,并且自身也会销毁。当向它发送drain消息时,只会释放里面吧的对象,而不会销毁自己。

3. ARC模式

当你在编译程序的时候提供自动管理内存的功能,它会自动加入内存的控制代码,控制对象的生命周期,大大简化了内存管理的步骤,ARC管理内容的原理就是,编译器会在适当的地方自动插入retain、release和autorelease消息

3.1 ARC机制下有几个明显的标志:

3.2 ARC的注意点和优点


3.3 ARC的判断原则

 Person *p1 = [[Person alloc] init];
 __strong  Person *p2 = [[Person alloc] init];

__weak  Person *p = [[Person alloc] init];

上一篇下一篇

猜你喜欢

热点阅读