最近项目开发中,临时被调去修复一个页面返回时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 野指针问题的更多相关文章

  1. C程序中可怕的野指针

    一.疑问点指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程序时,经常遇到的一种错误的使用方法,也许在你的学习和 ...

  2. C程序疑问解答 ——可怕的野指针

    本篇为原创,禁止任何形式的他用! 一.疑问点         指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程 ...

  3. 七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 4.@property参数 5.@class和循环retain的使用 6.NSString的内存管理

    1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程 ...

  4. OC-引用计数器,内存管理,野指针

    总结 全局断点 →-->+-->Add Exception Breakpoint 开启僵尸监听 打开Edit scheme -->Diagnostics-->Enable Zo ...

  5. iOS为真机调试增加scribble来定位野指针

    尽管在ARC中,野指针出现的频率已经大大降低了,但是仍然会有野指针困扰着我们. 在模拟器调试中,我们可以开启scribble或者zombieObject来将已经释放的内存填充无意义的内容,能够将一些非 ...

  6. NULL指针、零指针、野指针

    1.1.空指针 如果 p 是一个指针变量,则 p = 0; p = 0L; p = '\0'; p = 3 - 3; p = 0 * 17;p=(void*)0; 中的任何一种赋值操作之后, p 都成 ...

  7. 黑马程序员-nil Nil NULL NSNull 野指针和空指针

    空指针1.空指针指不含有任何内存地址的指针.在没有具体初始化之前,其被符值为0Dog * dog = nil;Dog * dog = NULL;都为空指针2.野指针指指向的内存为垃圾内存,导致其值不确 ...

  8. iOS--检测野指针

    定位野指针除了使用Malloc Scribble(内存涂鸦)外,还可以使用僵尸对象.所谓的僵尸对象,就是将被释放的对象标记为僵尸,系统不会回收这些对象的内存,并让这些内存无法被重用,因而也就不会被覆写 ...

  9. 使用AFNetworking时, 控制器点击返回销毁了, 但还是会执行请求成功或失败的block, 导致野指针异常

    原本我以为是我程序框架有问题...后来才知道, 无知真可怕... __unsafe_unretained __block typeof(self) weakSelf = self; AFHTTPSes ...

随机推荐

  1. 处理线上CPU负载过高的故障现象

    如何处理线上CPU100%的故障现象 处理流程: 1.登陆线上机器top命令,查看耗费cpu的进程号,举例来说发现进程24008持续耗费资源 2.top -Hp 24008去查看持续耗费cpu的线程号 ...

  2. Python - Django - 添加作者

    在 book_list.html 的页面下方加上 “添加作者” 的链接 <!DOCTYPE html> <html lang="en"> <head& ...

  3. Node.js使用ftp连接远程ftp服务器枚举和下载文件示例

    示例代码: var Ftp = require('ftp'); var fs = require('fs'); var path = require('path'); // 首先判断参数中是否包含{d ...

  4. ubuntu18.04安装chromium浏览器

    sudo add-apt-repository ppa:a-v-shkop/chromium sudo apt-get upate sudo apt-get install chromium-brow ...

  5. python:一行代码实现局域网共享文件

    其实就是使用python内置的一个模块http server 在python2中是下面这样的 python -m SimpleHTTPServer 80 解释下上面的参数,-m表示让python使用一 ...

  6. JWT(JSON Web Tokens)操作帮助类

    载荷实体: /// <summary> /// JWT载荷实体 /// </summary> public sealed class JWTPlayloadInfo { /// ...

  7. 使用自定义Comparator对TreeSet中的数据进行多条件排序

    代码记录(需求:根据店铺等级和店铺到某个点的距离进行排序,其中店铺等级由高到低,距离由近及远) 需要排序的对象Store,Store.java package com.zhipengs.work.te ...

  8. mysql 开启log-bin功能

      今天搜索了一下增量备份脚本,简单查了一下,增量备份是通过mysql binlog来做的,就是将某段时间内的操作,保存到某二进制日志当中.备份就是备这个日志,恢复也是通过它.然鹅,这里我们需要先开启 ...

  9. 乐字节Java变量与数据类型之一:Java编程规范,关键字与标识符

    大家好,我是乐字节的小乐,这次要给大家带来的是Java变量与数据类型.本文是第一集:Java编程规范,关键字与标识符. 一.编程规范 任何地方的名字都需要见名知意: 代码适当缩进 书写过程成对编程 对 ...

  10. java项目报错 :A class file was not written. The project may be inconsistent...

    问题: 打开ecplise,发现我的几个项目报错,上午还用的好好的,整我一脸懵,出现那么多错误还都是一种问题,错误提示翻译过来是:(类文件找不到) : 问题经过具体描述: 不只是在我的springMV ...