为什么程序设计要进行内存管理
1, 移动设备的内存,一般都极其有限, 所以每个APP能够分得的内存也是有限的
2, 当APP占用内存较多时,系统会发出内存警告, 这时得回收一些不再使用的内存空间,
3, 管理范围, 内存管理作用于任何继承了NSObject的对象, 一些基本数据类型, 如int ,double , short , enum 等则无需进行内存管理
因为这些变量存储在栈中,由系统自动释放
引用计数
每个O对象都有一个自己的引用计数,是一个整数 占4字节空间, 表示"对象被引用了多少次", 即有多少个指针指向并引用了这个对象
引用计数器的作用
当使用alloc,new或copy来创建一个新对象时, 新对象的引用计数默认为1
当一个对象的引用计数为0时,对象所占用的内存空间就会被回收. 如果引用计数不为0,则对象所占用内存空间就不会被回收,直到程序退出
引用计数器的操作
给对象发送一个retain消息, 则对象的引用计数会加1, retain返回对象本身
给对象发送一个release消息, 则对象的引用计数会减1.
给对象发送retainCount消息, 获得当前对象的引用计数值.
对象的销毁
当一个对象的引用计数为0时, 那么它所占用的内存就会被系统回收
当一个对象被销毁时,系统会自动向对象发送一条dealloc消息
一般会重写dealloc方法, 在这里进行释放资源的操作
一旦重写了dealloc, 就必须调用 [super dealloc], 并且放在最后边
不要直接调用dealloc
一旦对象被回收了, 所占用内存空间则不再可用, 如果仍坚持使用, 就会引发野指针错误
关闭ARC
为了能够进行手动内存管理,需要关键编译器的默认ARC内存管理机制
示例代码
//
// Person.h
// 引用计数
//
// Created by LiuWei on 15/4/16.
// Copyright (c) 2015年 LiuWei. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@end
//
// Person.m
// 引用计数
//
// Created by LiuWei on 15/4/16.
// Copyright (c) 2015年 LiuWei. All rights reserved.
//
#import "Person.h"
@implementation Person
// 当Person对象被回收时,系统会自动 调用 此方法
- (void)dealloc
{
NSLog(@"dealloc被调用");
// 一定要调用 super dealloc方法, 而且要放在最后边
[super dealloc];
}
@end
//
// main.m
// 引用计数
//
// Created by LiuWei on 15/4/16.
// Copyright (c) 2015年 LiuWei. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Person.h"
int main()
{
Person *p = [[Person alloc]init]; // 引用计数初始化为1
NSLog(@"retainCount: %ld", [p retainCount]);
[p retain]; // 引用计数 +1 返回值为对象本身
NSLog(@"retainCount: %ld", [p retainCount]);
[p release]; // 引用计数 -1
NSLog(@"retainCount: %ld", [p retainCount]);
[p release]; // 引用计数 -1 这时引用计数为0 系统调用 dealloc方法释放对象资源
// p.age = 10; 野指针错误
p = nil; // 当对象释放后,应当把指针重围为nil , 以防止发生野指针访问错误
// [p release]; 不可以对对象p再引用, 会此发野指针错误. 因为原对象空间已经被系统回收,不再可用.
[p release]; // p 为nil 所以不会报错, 此方法无效.
p.age = 10; // p 为nil 所以不会报错, 此方法无效.
return 0;
}
运行结果
打开僵尸对象功能图示
如果在程序中引用了僵尸对象, 打这僵尸对象功能, 生成程序则会对引用僵尸对象进行报错和提示.