MRC下delegate 野指针问题
最近项目开发中,临时被调去修复一个页面返回时crash的问题。出现这个问题的原因也很巧合,正好服务地址在同事电脑上,也正巧网络请求响应时间狂慢!一个请求发出去回来的时间是40秒左右,要是在线上,肯定会让用户抓狂死!
当我打开项目的时候,点击页面返回时,发现网络请求依然在请求中,第一感觉就是内存管理上出错。在全局断点中定位到出问题的点上,竟然是delegate回调的地方出现了问题!
if (self.delegate && [self.delegate respondsToSelector:@selector(test:)]) {
[self.delegate test:nil];
}
这段代码在iOS开发中随处可见,而且其正确性在现在版本中毋庸置疑。一开始我并没有以为是delegate这边出错,因为我查了下property的确是assign。在ViewController里面又查了下相关内存操作,在dealloc中发现一个严重问题,我的VC都销毁了,里面对象竟然木有销毁,这的确很诡异。由于项目中结构有点奇葩,属于MVC重度用户!未销毁的对象就是我们所谓的负责业务逻辑的对象,在对其引用的地方只有网络请求的地方,在调用函数参数中delegate设置为self。在iOS开发中,我们会将网络请求放入到一个队列中,在网络请求成功后,在队列中取出网络请求相关信息,并移除此请求。由于在将网络请求加入到队列中对传进来的self进行了强引用,所以这个可以解释为什么我们业务处理对象引用计数为什么会大于1,而导致不能销毁。虽然这在设计上来说的确存在不合理性,我只需一个delegate而不需要对调用对象进行强引用。但仔细想想这个不至于导致程序挂掉,虽然我对你调用对象进行了引用计数加1,大不了内存迟点释放,走遍回调,我实际调用的VC已经是nil了所以也不会调用。
就是这个我认为VC一定是nil,毕竟我看到它在内存中销毁了。将Xcode debug中zombie objects勾上,重新调试,结果控制台中打印出 message sent to deallocated instance 0x90a3900,彻底改变了我的世界观!delegate不是nil。。。。可是我的delegate的确是assign啊!这是为什么呢?最根本的原因是将ARC中weak和MRC中的assign给混为一谈了。。。。
weak和assign对传入的对象不会改变引用计数的变化。所以发现我们的delegate,在MRC中是assign,在ARC中是weak。但是这两点有什么区别呢?两者都可以保证对传入的对象不会改变引用计数,但是weak对象必须是oc对象。weak比assign强大的地方就是在指向的对象销毁时,所有指向该对象的weak指针都会置为nil。这样我们就可以写出如此简洁的判断if (self.delegate && [self.delegate respondsToSelector:@selector(test:)])。而在MRC中,如果直接写这样的代码,如果调用者在对象销毁时未将delegate置为nil,delegate将变成野指针,而导致程序挂掉。这也是为什么苹果官方推荐大家是用ARC,ARC在很多地方都可以保证程序的健壮性。
MRC下delegate 野指针问题的更多相关文章
- C程序中可怕的野指针
一.疑问点指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程序时,经常遇到的一种错误的使用方法,也许在你的学习和 ...
- C程序疑问解答 ——可怕的野指针
本篇为原创,禁止任何形式的他用! 一.疑问点 指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程 ...
- 七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 4.@property参数 5.@class和循环retain的使用 6.NSString的内存管理
1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程 ...
- OC-引用计数器,内存管理,野指针
总结 全局断点 →-->+-->Add Exception Breakpoint 开启僵尸监听 打开Edit scheme -->Diagnostics-->Enable Zo ...
- iOS为真机调试增加scribble来定位野指针
尽管在ARC中,野指针出现的频率已经大大降低了,但是仍然会有野指针困扰着我们. 在模拟器调试中,我们可以开启scribble或者zombieObject来将已经释放的内存填充无意义的内容,能够将一些非 ...
- NULL指针、零指针、野指针
1.1.空指针 如果 p 是一个指针变量,则 p = 0; p = 0L; p = '\0'; p = 3 - 3; p = 0 * 17;p=(void*)0; 中的任何一种赋值操作之后, p 都成 ...
- 黑马程序员-nil Nil NULL NSNull 野指针和空指针
空指针1.空指针指不含有任何内存地址的指针.在没有具体初始化之前,其被符值为0Dog * dog = nil;Dog * dog = NULL;都为空指针2.野指针指指向的内存为垃圾内存,导致其值不确 ...
- iOS--检测野指针
定位野指针除了使用Malloc Scribble(内存涂鸦)外,还可以使用僵尸对象.所谓的僵尸对象,就是将被释放的对象标记为僵尸,系统不会回收这些对象的内存,并让这些内存无法被重用,因而也就不会被覆写 ...
- 使用AFNetworking时, 控制器点击返回销毁了, 但还是会执行请求成功或失败的block, 导致野指针异常
原本我以为是我程序框架有问题...后来才知道, 无知真可怕... __unsafe_unretained __block typeof(self) weakSelf = self; AFHTTPSes ...
随机推荐
- osg::Camera example
#ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include<iostream> #include <osgV ...
- ClientDataSet中修改,删除,添加数据和Delta属性
ClientDataSet中使用Post提交变更的数据时,实际上并没有更新到后端数据库中,而是提交到了由DataSnap管理的数据缓冲区中.当使用了ClientDataSet.ApplyUpDates ...
- ElasticSearch——路由(_routing)机制
前言 一条数据是如何落地到对应的shard上的? 当索引一个文档的时候,文档会被存储到一个主分片中. Elasticsearch 如何知道一个文档应该存放到哪个分片中呢? 首先这肯定不会是随机的,否则 ...
- JS时间转换,url编码,jquery返回类型等问题
1.当时间被转换为json格式后会被转换成 /Date(...)/ 这种格式,其中...为时间转换成妙后的一串整数 function changeDateFormat(cellval) { )); v ...
- python reduce和偏函数partial
functools模块 reduce方法: reduce方法 reduce方法,顾名思义就是减少 可迭代对象不能为空,初始值没提供就在可迭代对象中去一个元素 from functools import ...
- jquery控制一个元素是否显示
比如说我有一个id为dlg-buttons的div元素. 我可以通过 $('#dlg-buttons').show(); 让他显示出来: 可以通过 $('#dlg-buttons').hide(); ...
- C,OC,C++语言对比
1.C与OC.C++的区别: C语言的特点:面向过程 1)C语言是结构化语言,层次清晰,调试和维护比较容易 2)表现能力和处理能力比较强,可直接访问内存的物理地址 3)c语言实现对硬件的编辑,c语言课 ...
- AWS 核心服务概述(二)
目录 AWS网络服务 VPC Direct Connect Route53 AWS 计算服务 EC2 EMR(Elastic MapReduce) AWS Lambda Auto Scaling El ...
- 【C/C++开发】内存对齐(内存中的数据对齐)、大端模式及小端模式
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...
- Python函数或者类的时间参数的默认值设为datetime.date.today()引起的问题
定义了函数def main(start_date=datetime.date.today(), end_date=datetime.date.today()): pass 函数在项目启动后, end_ ...