ARC 下代理产生内存泄漏的情况
2016-09-03 10:45
211 查看
在ARC下依然会发生内存泄漏的情况,比如在使用代理的时候,A有个属性参照B,B有个属性参照A,如果将各自的对象的属性设为strong属性,因为两个对象都无法释放,就会发生内存泄漏的现象;
比如Person类让Agent对象去查看每张票的价钱并统计还剩多少张票,而Agent 让Person对象去统计有多少人去看电影,二者相互引用对方作为自己的成员变量,就会发生内存泄漏的现象,代码如下:
Person.h
使用系统自带的工具Instruments(Xcode—>Product—>Profile—>leaks) 里面的leaks工具查看一下有无内存泄漏:
由图可知内存放生了泄漏;工具中选择Cycle & Roots 可以根据图清楚的看到两个对象发生了循环引用:
为什么会发生内存泄漏呢?让我们看一下两个对象各自的引用计数的情况
所以当我们创建各自的对象的时候引用计数为1,当相互引用对方作为代理的时候引用计数为2 ,最后ARC使用autorelease 一次各自对象的引用计数又变为1 ,所以这个时候两个对象都没有释放,就发生了内存泄漏的现象;
@property(nonatomic,assign)Person
*delegate2;
更换之后再次使用工具进行内存泄漏检测:这个时候就不发生内存泄漏的情况了
代码打印的结果为:
比如Person类让Agent对象去查看每张票的价钱并统计还剩多少张票,而Agent 让Person对象去统计有多少人去看电影,二者相互引用对方作为自己的成员变量,就会发生内存泄漏的现象,代码如下:
Person.h
#import <Foundation/Foundation.h> @class Agent; @interface Person : NSObject //Person拥有一个代理属性Agent @property(nonatomic,strong)Agent *delegate; -(void)buyTicket; -(int)num; @endPerson.m
#import "Person.h" #import "Agent.h" @implementation Person -(void)buyTicket{ //Person让代理对象_delegate去统计还剩多少张票 int left= [_delegate leftTicketNumber]; //Person让代理对象_delegate去查看每张票的价钱 double price =[_delegate ticketPrice]; NSLog(@"剩余票数是 %d 每张票的价钱是%f",left,price); } -(int)num{ return 100; } @endAgent.h
#import <Foundation/Foundation.h> @class Person; @interface Agent : NSObject -(int)leftTicketNumber; -(double)ticketPrice; //agent拥有代理对象Person @property(nonatomic,retain)Person *delegate2; -(void)numberOfPeople; @endAgent.m
#import "Agent.h" #import "Person.h" @implementation Agent -(int)leftTicketNumber{ return 2; } -(double)ticketPrice { return 1000; } -(void)numberOfPeople { //agent让代理对象 _delegate2去计算一共有多少人 int n =[_delegate2 num]; NSLog(@"一共有%d个人",n); } @end二者相互引用对方作为自己的代理对象
Person *person =[[Person alloc]init]; Agent *agent =[[Agent alloc]init]; person.delegate=agent; [person buyTicket]; agent.delegate2=person; [agent numberOfPeople];代码执行情况:
使用系统自带的工具Instruments(Xcode—>Product—>Profile—>leaks) 里面的leaks工具查看一下有无内存泄漏:
由图可知内存放生了泄漏;工具中选择Cycle & Roots 可以根据图清楚的看到两个对象发生了循环引用:
为什么会发生内存泄漏呢?让我们看一下两个对象各自的引用计数的情况
Person *person =[[Person alloc]init]; Agent *agent =[[Agent alloc]init]; //使用CFGetRetainCount((__bridge CFTypeRef)(obj))方法打印对象的引用计数 NSLog(@"%ld",CFGetRetainCount((__bridge CFTypeRef)(person))); NSLog(@"%ld",CFGetRetainCount((__bridge CFTypeRef)(agent))); person.delegate=agent; [person buyTicket]; agent.delegate2=person; NSLog(@"=======%ld",CFGetRetainCount((__bridge CFTypeRef)(person))); NSLog(@"=======%ld",CFGetRetainCount((__bridge CFTypeRef)(agent))); [agent numberOfPeople];代码执行情况:
所以当我们创建各自的对象的时候引用计数为1,当相互引用对方作为代理的时候引用计数为2 ,最后ARC使用autorelease 一次各自对象的引用计数又变为1 ,所以这个时候两个对象都没有释放,就发生了内存泄漏的现象;
Person *person =[[Person alloc]init]; // person引用计数为1: Agent *agent =[[Agent alloc]init]; //agent引用计数为1 person.delegate=agent; //agent retain一次:引用计数为2 [person buyTicket]; agent.delegate2=person; //person retain一次:引用计数为2 [agent numberOfPeople];解决办法:将循环参照的两个对象的其中一个的属性设置为assign(简单赋值,不改变引用计数)
@property(nonatomic,assign)Person
*delegate2;
更换之后再次使用工具进行内存泄漏检测:这个时候就不发生内存泄漏的情况了
代码打印的结果为:
相关文章推荐
- C++类对象之间赋值产生内存泄漏的一种情况
- ARC下会导致内存泄漏的情况
- 产生 java.lang.NoClassDefFoundError 的另一种意外情况:jar包部分的物理性损坏
- 产生 java.lang.NoClassDefFoundError 的另一种意外情况:jar包部分的物理性损坏
- 产生 java.lang.NoClassDefFoundError 的另一种意外情况:jar包部分的物理性损坏
- [置顶] 输出cglib以及jdk动态代理产生的class文件
- MFC内存泄漏的问题的其中一种情况
- Jackson高并发情况下,产生阻塞
- 第十周项目一 阅读下面的定义,请说出在测试函数中不同情况的调用产生的结果(5 a)
- "每日一道面试题".net托管堆是否会存在内存泄漏的情况
- 分享一个使一行文字变形产生弯曲弧度特效的jQuery插件 - Arctext.js 编辑
- C++中内存泄漏的几种情况
- C#Random在多线程情况下产生的随机数总是0的问题
- 在客户使用透明代理的情况下正确得到其IP地址
- 阅读类的定义,说出测试函数中不同情况的调用产生的结果
- Android 内存泄漏和内存溢出情况总结
- 内存泄漏的情况
- 内存管理 ARC情况下
- 关于STSDB4在不commit的情况下是否会对内存数据库产生影响
- 什么情况导致内存泄漏