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将变成野指针,而导致程序挂掉。所以在dealloc中[xxx
release]前,加上xxx.delegate = nil。这也是为什么苹果官方推荐大家是用ARC,ARC在很多地方都可以保证程序的健壮性。

时间: 2024-11-12 03:40:35

MRC下delegate野指针问题的相关文章

MRC下delegate 野指针问题

最近项目开发中,临时被调去修复一个页面返回时crash的问题.出现这个问题的原因也很巧合,正好服务地址在同事电脑上,也正巧网络请求响应时间狂慢!一个请求发出去回来的时间是40秒左右,要是在线上,肯定会让用户抓狂死! 当我打开项目的时候,点击页面返回时,发现网络请求依然在请求中,第一感觉就是内存管理上出错.在全局断点中定位到出问题的点上,竟然是delegate回调的地方出现了问题! if (self.delegate && [self.delegate respondsToSelector:

C程序中可怕的野指针

一.疑问点指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程序时,经常遇到的一种错误的使用方法,也许在你的学习和工作中就是这样用的,很危险.实例程序如图1所示: 图1 实例程序这段程序比较简单,str1指向的内存区域存放了一个字符串"123",把"123"赋值到str2指向的内存区域,编译时会给出一个告警:local variable 'str2' used without ha

一个双线程下同时操作指针变量导致野指针出现的问题总结

来源:http://blog.csdn.net/lezhiyong 问题: 在某项目的测试过程中,测试在高清压力测试过程中会偶尔出现RSS崩溃现象,崩溃时间不确定,由于在守护进程服务的守护下,RSS崩溃后被重新拉起,所以这个故障在崩溃马上发送时在网管上并没有体现服务停止的告警,只有当测试人员去RSS的var/run目录下找到edum***开头的文件才指定RSS发送崩溃.根据文件中提供的崩溃时间描述,有时是几天前的,有时是几个小时前的,测试人员较难回忆其当时做了什么操作.根据多个edum***文件

七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 [email protected]参数 [email protected]和循环retain的使用 6.NSString的内存管理

1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程序闪退. 2.OC内存管理的范围 : 管理任何继承NSObject的对象,对其他的基本数据类型无效. 3.对象类型是程序运行过程中动态分配的,存储在堆区:内存管理主要是对 堆区中的对象的内存管理. 4.OC内存管理的原理 为了防止内存泄露 对象的引用计数器 : 每个OC对象都有自己的引用计数器,是一

关于空指针NULL、野指针、通用指针

http://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了.假设 有语句 int a=10;那么编译器就在内存中开辟1个整型单元存放变量a,我们假设这个整型单元在内存中的地址是 0x1000:那么内存0x1000单元中存放了数据10,每次我们访问a的时候,实际上都是访问的0x1000单元中的10.现在定义:int *p:                 p=&a

c++中的悬浮指针和野指针 二级指针

(1) c++中的悬浮指针:声明了但没有被付值的指针,它指向内存中的任意一个空间.避免悬浮指针的一个方法是开始就付值为NULL (2)"野指针"不是NULL指针,是指向"垃圾"内存的指针.人们一般不会错用NULL指针,因为用if语句很容易判断.但是"野指针"是很危险的,if语句对它不起作用.野指针的成因主要有两种: 一.指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同

View野指针问题分析报告

[问题描述] 音乐组同事反馈了一个必现Native Crash问题,tombstone如下: pid: 5028, tid: 5028, name: com.miui.player >>> com.miui.player <<< signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 79801f28 r0 7ac59c98 r1 00000000 r2 bea7b174 r3 400fc1b8 r4 774c4c88

Virsualizer模块野指针问题分析报告

[NE现场] pid: 1040, tid: 19988, name: Visualizer >>> com.android.systemui <<< signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 546f2cf8 r0 56106e28 r1 546f2d18 r2 0200000f r3 02000008 r4 56106e28 r5 546f2d18 r6 566f2d24 r7 566f2d20 r8

C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

(1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放,造成内存泄露,下面的例子就可能造成20个字节的泄露,内存泄露不是一个立即会引发故障的错误,但是 它将消耗系统内存. void function1() { char *pa; pa = (char*)malloc(sizeof(char)*20); if(NULL !=pa) { strcpy(pa,"hello"); printf("pa = %x\n",