码迷,mamicode.com
首页 > 其他好文 > 详细

OC内存管理(MRC)

时间:2015-07-14 00:05:31      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

首先说明一下几块存储区域:栈区(局部变量、函数参数值)、堆区(对象、手动申请/释放内存)、BSS区(未初始化的全局变量、未初始化的静态数据)、常量区(字符串常量以及初始化后的全局变量、初始化后的静态数据)、代码区(存放函数体的二进制代码)

 

 

 1.为什么需要内存管理

    由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当某个APP所占用的内存超过系统规定限定内存大小时,系统就会发出内存警告,系统会向该APP发送Memory Warning消息。收到此消息后,需要该APP回收一些不需要再继续使用的内存空间,如果该APP不理会这个消息,系统会强制退出这个程序(程序会崩溃)。

 

 2.内存管理范围

    所有的OC对象,对其他的数据类型无效,因为OC对象存放在堆区,堆区内存不会自动释放,而其他数据类型存放在栈区(实际上系统为在栈区的数据自动加上了autorelease消息),至于为什么对象是存放在堆区,而其他数据类型是存放在栈区,是因为其他数据类型存储空间是固定的,比如,int4个字节,double8个字节等等,而对象是在程序运行时动态分配存储空间的,不是固定的大小所以存放在堆区.

 

 3.内存管理操作

    每个对象内部都有8个字节存储计数器(unsigned long类型)

    计数器显示的是当前对象的被引用的次数

    计数器是判断对象内存是否需要回收的唯一依据,当计数器为0时,对象将被回收(存在一个例外,那就是对象值为nil时)

    任何一个对象刚创建出来时,计数器为1

 

    给对象发送消息,进行相应的计数器操作。 

    retain消息:使计数器+1,该方法返回对象本身 

    release消息:使计数器-1(并不代表释放对象) 

    retainCount消息:获得对象当前的引用计数器值 %ld %tu

    

    当一个对象计数器为0的时候,对象回收之前会自动调用dealloc方法,类似于一个对象在回收之前的消息返回(或者说是"临终遗言"),一般会重写dealloc方法.

 1 #import <Foundation/Foundation.h>
 2  @interface Car : NSObject
 3  
 4  //定义了一个int类型的实例变量speed
 5  @property(nonatomic,assign,readwrite) int speed;
 6  
 7  @end
 8  
 9  
10  #import "Car.h"
11  
12  @implementation Car
13 
14  - (void)dealloc{
15     NSLog(@"速度为%d的车子挂了",_speed);
16     [super dealloc];
17  }
18  
19  @end
20 
21  #import <Foundation/Foundation.h>
22  @class Car;
23  
24  @interface Person : NSObject
25  
26  //将Car类型的类作为实例变量
27  @property(nonatomic,retain,readwrite) Car *car;
28  
29  @end
30  
31  #import "Person.h"
32  #import "Car.h"
33  
34  @implementation Person
35  - (void)dealloc{
36  
37  [_car release];
38  NSLog(@"Person 挂了");
39  
40  [super dealloc];
41  }
42  @end
43  
44  
45  #import <Foundation/Foundation.h>
46  #import "Car.h"
47  #import "Person.h"
48  
49  int main(int argc, const char * argv[]) {
50  @autoreleasepool {
51  
52  Person *p = [[Person alloc] init];
53  Car *bigBen = [[Car alloc] init];
54  Car *byd = [[Car alloc] init];
55  
56  bigBen.speed = 200;
57  byd.speed = 300;
58  
59  //这里将bigBen给p这个对象时,使用@property生成的set方法中,对当前传进来的对象进行判断,是否与当前对象相同,不相同则对传进来的对象计数器做一次retain操作.
60  p.car = bigBen;
61  //同理  所以在p的dealloc方法中对当前_car做了一次release操作
62  p.car = byd;
63  
64  //打印计数器当前值
65  NSLog(@"当前p的计数器为:%lu",[p retainCount]);
66  
67  [p release];
68  
69  [bigBen release];
70  [byd release];
71  
72  }
73  return 0;
74  }

上面的代码就综合使用到了retain,release,retainCount方法,还有dealloc方法的重写,这里特别说明的是dealloc方法重写一定要写[super dealloc],因为子类继承父类(或者一个类关联另一个类),父类(另一个类)会有私有变量/私有方法等(可见不可访问)需要调用父类(另一个类)的dealloc方法来彻底回收父类在子类中的那块内存.

 

 

 

 4.内存管理注意事项

    当一个对象计数器为0,自动调用了dealloc方法时,再对该对象进行retain操作是野指针操作(野指针:指向了僵尸对象的指针),开启了检测僵尸对象会报错(Edit Scheme中打开僵尸对象检测)

    谁创建,谁release;谁retain,谁release;谁调用,谁release(有始有终,谁让计数器+1,就应该让计数器-1)

    永远不要直接通过对象调用dealloc方法(实际上调用并不会出错)

    一旦对象被回收了, 它占用的内存就不再可用, 坚持使用会导致程序崩溃(野指针错误)为了防止调用出错,可以将“野指针”指向nil(0)

 

OC内存管理(MRC)

标签:

原文地址:http://www.cnblogs.com/lizzie8023/p/4644193.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!