iOS中常见的 Crash 场景以及解决方法
1. 常见的 Crash 场景
-
访问了僵尸对象
-
访问了不存在的方法
-
数组越界
-
在定时器下一次回调前将定时器释放,会Crash
2. 关于BAD_ACCESS
出现的原因: 访问了野指针, 比如访问已经释放对象的成员变量或者发消息, 死循环等;
解决方法:
1. 重写对象的respondsToSelector 方法, 先找到出现 EXECBADACCESS 前访问的最后一个 object;
2. 设置Enable Zombie Objects;
3. 设置全局断点快速定位问题代码所在行,接收所有异常;
4. Xcode7 之后已经集成了 BAD_ACCESS 捕获功能: Address Sanitizer 与步骤 2 一样设置;
5. analyze(静态分析, 不一定管用)
3. 什么时候会报 unrecognized selector 异常
-
当调用对象(子类,各级父类)中不含有对应方法的时候,并且依旧没有给出“消息转发”的具体方案的时候,程序在运行时会crash并抛出 unrecognized selector 异常
-
objective-c 中的每个方法在运行时会被转为消息发送objc_msgSend(reciver, selector)
-
例如 [person say]就会被转化为 objc_msgSend(person, @selector(say))
-
运行时会根据对象(reciever) 的isa 指针找到该对象所对应的类,然后会依次在对应的 类,父类,爷爷类,根类中找对应的方法
下面讲述对象方法的解析过程:
-
第一步:+(BOOL)resolveInstanceMethod:(SEL)sel实现方法,指定是否动态添加方法。 若返回NO,则进入下一步,若返回YES,则通过class_addMethod函数动态地添加方 法,消息得到处理,此流程完毕。
-
第二步:在第一步返回的是NO时,就会进入- (id)forwardingTargetForSelector:(SEL)aSelector方法,这是运行时给我们的第二次机会,用于指定哪个对象响应这个selector。不能指定为self。若返回nil,表示没有响应 者,则会进入第三步。若返回某个对象,则会调用该对象的方法。
-
第三步:若第二步返回的是nil,则我们首先要通过- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector指定方法签名,若返回nil,则表示不处 理。若返回方法签名,则会进入下一步。
-
第四步:当第三步返回方法方法签名后,就会调用- (void)forwardInvocation:(NSInvocation *)anInvocation方法,我们可以通过anInvocation 对象做很多处理,比如修改实现方法,修改响应对象等
-
第五步:若没有实现- (void)forwardInvocation:(NSInvocation *)anInvocation方法,那么 会进入- (void)doesNotRecognizeSelector:(SEL)aSelector方法。若我们没有实现这个方 法,那么就会crash,然后提示打不到响应的方法。到此,动态解析的流程就结束了。
4. 如何解决很难复现的crash
1. 有错误日志先看错误日志信息,
2.没有错误日志,第一步分析函数中的所有分支, 是否在语法上存在可能缺少条件的问题.所以检查所以的分支,确保每个分支执行的结果是正确的.
3.检查函数的参数,保证必传参数不能为空,若为空应该抛出异常,因此用断言检查参数的正确性很重要
4.检查函数中每个分支所调用的函数返回结果是正确的,其实就是递归过程(重复2,3步骤)
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· MQ 如何保证数据一致性?
· 一个基于 .NET 开源免费的异地组网和内网穿透工具