内存管理(2)

来源:互联网 发布:mac窗口最小化快捷键 编辑:程序博客网 时间:2024/05/18 00:04

6.【掌握】单个对象内存管理

1、【掌握】避免使用僵尸对象的方法

  • 为了防止不小心调用了僵尸对象,可以将对象赋值nil(对象的空值)

    • 给空指针发消息是没有任何反应的。
        Student *s = [[Student alloc] init];  [s release];  s = nil;  // 打印对象的引用计数器值NSLog(@"%lu",[s retainCount]);

2、【掌握】对象的内存泄露

  • 1.retain和release的个数不匹配,导致内存泄露。

  • 2.对象使用的过程中被赋值了nil,导致内存泄露
    这里写图片描述

  • 3.在函数或者方法中不当的使用retain 或者 release 造成的问题
    这里写图片描述

7.【掌握】多个对象内存管理(野指针)

  • 单个对象的内存管理,看起来非常简单。
  • 如果对多个对象进行内存管理,并且对象之间是有联系的,那么管理就会变得比较复杂。

  • 其实,多个对象的内存管理思路,跟管理游戏房间类似:

  • 如:劲舞团,LOL
    // 1、创建玩家对象    Gamer *game = [[Gamer alloc] init];    // 2、创建房间对象    Room *room = [[Room alloc] init];    // 3、让玩家进入房间    game.room = room;    // 4、释放房间对象    [room release];    // 5、输出玩家的房间    NSLog(@"玩家的房间是:%@",game.room);
  • 此时,会报野指针错误。

8、【掌握】多个对象内存管理

  • 解决方案:在使用房间时,对房间进行一次release。
// 声明类@interface Gamer : NSObject{    Room *_room;}- (void)setRoom:(Room *)room;- (Room *)room;// 实现类@implementation Gamer- (void)setRoom:(Room *)room{    [room retain];    _room = room;}- (Room *)room{    return _room;}- (void)dealloc{    NSLog(@"玩家被释放");    [super dealloc];}@end// main函数实现  // 1、创建玩家对象    Gamer *game = [[Gamer alloc] init];    // 2、创建房间对象    Room *room = [[Room alloc] init];    // 3、让玩家进入房间    game.room = room;    // 4、释放房间对象    [room release];    // 5、输出玩家的房间    NSLog(@"玩家的房间是:%@",game.room);
  • 问题:房间无法被释放了怎么办?

  • 解决方法:

    • 在对象被释放时,要把该对象的所有对象类型的成员变量在dealloc当中进行释放:
@implementation Gamer- (void)dealloc{    [_room release];    NSLog(@"玩家被释放");    [super dealloc];}@end
  • 需求:让玩家反复进入这个房间。
int main(int argc, const char * argv[]) {    @autoreleasepool {        Gamer *g = [Gamer new];        Room *r = [Room new];        g.room = r;        g.room = r;        g.room = r;        [g release];        [r release];    }    return 0;}
  • 问题:房间对象无法被释放,怎么办?

  • 解决方案:判断新进房间与之前是否是同一个房间。

- (void)setRoom:(Room *)room{    if (_room != room) {        [room retain];        _room = room;    }}
  • 总的来说,有以下几点规律:
    • 1)只要还有人使用某对象,那么这个对象就不会被回收。
    • 2)只要想要使用1个对象,那么就让对象的引用计数器+1。
    • 3)当不再使用这个对象时,就让对象的引用计数器-1。

9、【掌握】set方法内存管理

  • 需求:
    • 1、让玩家换房间,进入1号房间后,再进入2号房间
// 实现玩家类 @implementation Gamer- (void)setRoom:(Room *)room{    [_room release];    _room = [room retain];}- (Room *)room{    return _room;}- (void)dealloc{    [_room dealloc];    NSLog(@"玩家被释放");    [super dealloc];}@endint main(){    // 1、创建玩家对象    Gamer *game = [[Gamer alloc] init];    // 2、创建房间对象    Room *room = [[Room alloc] init];    room.no = 1;    Room *room1 = [[room alloc] init];    room.no = 2;    // 3、让玩家进入房间    game.room = room;    game.room = room1;    // 4、释放房间对象    [room release];    // 5、释放玩家对象    [game release];    return 0;    }
  • 问题:房间对象再次无法被释放
  • 解决方案:
- (void)setRoom:(Room *)room{    if (_room != room)    {        // 释放旧房间        [_room release];        [room retain];        _room = room;    }}
  • 总结:
  • 1、set方法的内存管理
- (void)setRoom:(Room *)room{    if(_room != room){    [_room release];    _room = [room retain];  }}
  • 2、dealloc方法内存管理
- (void)dealloc{    // 当玩家不在了,代表不用房间了    // 对房间进行一次release    [_room release];    // 重写dealloc方法,必须在最后调用父类的dealloc方法    [super dealloc];}
  • 常见错误写法
  • 会引发内存泄露
    objc
    gamer.room = [[Room alloc] init];
    [[Room alloc] init].no= 10;
0 0