A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 崔石炫 中级黑马   /  2014-9-26 00:29  /  1735 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

看到多对象内存管理的视频,产生了一个疑问,首先看以下代码,就不用老师写的PersonBook了,用QQ堂游戏模拟吧:
  1. //GameRoom类,表示游戏房间
  2. @interface GameRoom : NSObject
  3. {
  4.         int _roomNumber;
  5. }
  6. - (void)setRoomNumber:(int) roomNumber;
  7. - (NSSting *) roomNumber;
  8. @end

  9. @implementation GameRoom
  10. - (void)setRoomNumber:(int) roomNumber
  11. {
  12.         _ roomNumber = roomNumber;
  13. }
  14. - (NSSting *) roomNumber
  15. {
  16.         return _ roomNumber;
  17. }
  18. - (void)dealloc
  19. {
  20.         NSLog(@” GameRoom对象被释放”);
  21.         [super dealloc];
  22. }
  23. @end

  24. //Player类,表示游戏玩家
  25. @interface Player : NSObject
  26. {
  27.         GameRoom *_gameRoom; // 目前所在的游戏房间
  28. }
  29. - (void)setGameRoom:(GameRoom*)gameRoom;
  30. - (GameRoom*)gameRoom;
  31. @end

  32. @implementation Player
  33. - (void)setGameRoom:(GameRoom*)gameRoom
  34. {
  35.         _ gameRoom = [gameRoom retain];
  36. }
  37. - (GameRoom*)gameRoom
  38. {
  39.         return _ gameRoom;
  40. }
  41. - (void)dealloc
  42. {
  43.         [_ gameRoom release]; // 使引用的GameRoom对象的引用计数器减1
  44. NSLog(@”Player对象被释放”);
  45.         [super dealloc];
  46. }
  47. @end

  48. //main函数
  49. int main()
  50. {
  51.         GameRoom *room = [[GameRoom alloc] init];        //alloc出来的对象引用计数为1
  52.         Player *player = [[Player alloc] init];                        //alloc出来的对象引用计数为1

  53.         [player setGameRoom:room];                                //room对象引用计数器+1,为2

  54.         [room release];                                                        //room对象引用计数器-1,为1
  55.         room = nil;

  56.         [player release];                                                       
  57.         /*player对象引用计数器-1,为0.
  58.           系统发送dealloc消息,内部向room发送release消息
  59.           room对象引用计数器-1,为0
  60.         */
  61.         player = nil;

  62.         return 0;
  63. }
复制代码

分析:
以上代码,是没有问题的,程序运行结束时,两个对象都被回收。
现在的问题是:
如果我在main函数中[player release];处重多次复调用playerset方法,
即写多次[player release];,重复设置其_gameRoom属性为room对象,
使room对象引用计数器多次+1,其他代码不变。
最后:
程序运行结束后room对象的引用计数器值还是不为0,导致内存泄露。

4 个回复

倒序浏览
修改下player类中的 - (void)setGameRoom:(GameRoom*)gameRoom方法
- (void)setGameRoom:(GameRoom*)gameRoom
{
        if(_gameRoom != gameRoom){
            [ _gameRoom  release];            _gameRoom = [gameRoom retain];
         }
}

回复 使用道具 举报
你是说这样:
[player setGameRoom:room];
[player setGameRoom:room];
[player setGameRoom:room];

其实这样多次重复传入同一个参数是没有意义的,你可以这样:

  1. - (void)setGameRoom:(GameRoom*)gameRoom
  2. {
  3.         //先判断传进来的对象是否重复传入
  4.         if(_gameRoom != gameRoom)
  5.         {
  6.                 //release旧对象,以便接收新对象
  7.                 [_gameRoom release];
  8.                
  9.                 //retain新对象
  10.                 _ gameRoom = [gameRoom retain];
  11.         }
  12. }
复制代码
回复 使用道具 举报
AngleMGG 发表于 2014-9-26 00:53
你是说这样:
;
;

set方法不会使计数器加1吧?
回复 使用道具 举报
AngleMGG 发表于 2014-9-26 00:53
你是说这样:
;
;

虽说没有意义,但总有人会手抖。:lol
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马