iOS常见崩溃简介

1. 崩溃

多指在移动设备(如iOS、Android设备)中或不可移动设备(如:Windows、Linux等设备),
在打开或使用应用程序时出现的突然退出中断的情况(类似于Windows的应用程序崩溃)。

多表现为:应用程序画面一闪而过,随即退回到桌面。

崩溃会影响用户体验,造成用户流失,因此,我们要重视崩溃
在这里插入图片描述

根据不同场景,崩溃收集方式不同

Xcode编译期间:

在这里插入图片描述

测试机获取:

Xcode->Window->Devices and Simulators
在这里插入图片描述
或者
设置->隐私->分析与改进

线上崩溃采集:

封装好的三方,直接接入的:友盟、bugly、听云
开源的SDK:KSCrash、plcrashreporter

2. 崩溃产生的原因

划分方式一:

  • cpu无法执行的代码
  • 被系统强杀
  • 语言触发异常

2.1 cpu无法执行的代码

  • 无效指令或操作
  • 访问无效地址及不具有权限的内存地址
  • 除以0等
  • 僵尸对象

2.2 被系统强杀

  • 应用内存消耗过高,即OOM问题
  • 主线程长时间无法响应ANR
  • 资源异常
  • 死锁
  • 非法的应用签名
  • 后台执行超时

2.3 语言触发异常

  • OC语言抛出异常
  • C++抛出异常

划分方式二:

除了上面的划分方式,崩溃还可以按:软件异常硬件异常划分

软件异常:
软件异常主要来自 kill(),pthread_kill()。iOS 中的 NSException 未捕获,abort 都属于这种情况。

硬件异常:
硬件的信号始于处理器 trap,是和平台相关的。野指针崩溃大部分是硬件异常。

软件异常的流程是:

软件异常 -> Unix信号

硬件异常的流程是:

硬件异常 -> Mach异常 -> Unix信号
在这里插入图片描述

在这里插入图片描述

Mach 异常:

  • EXC_BAD_ACCESS: 不能访问的内存
  • EXC_BAD_INSTRUCTION: 非法或未定义的指令或操作数
  • EXC_ARITHMETIC: 算术异常(例如除以0)。iOS 默认是不启用的,所以我们一般不会遇到
  • EXC_EMULATION: 执行打算用于支持仿真的指令
  • EXC_SOFTWARE:软件生成的异常,我们在 Crash 日志中一般不会看到这个类型,苹果的日志里会是 EXC_CRASH
  • EXC_BREAKPOINT:跟踪或断点
  • EXC_SYSCALL: UNIX 系统调用
  • EXC_MACH_SYSCALL: Mach 系统调用

UNIX 信号:

  • SIGSEGV,段错误。访问未分配内存、写入没有写权限的内存等。
  • SIGBUS,总线错误。比如内存地址对齐、错误的内存类型访问等。
  • SIGILL,执行了非法指令,一般是可执行文件出现了错误。
  • SIGFPE ,致命的算术运算。比如数值溢出、NaN数值等。
  • SIGABRT,调用 abort() 产生,通过 pthread_kill() 发送。
  • SIGPIPE,管道破裂。通常在进程间通信产生。比如采用FIFO(管道)通信的两个进程,读管道* 没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。根据苹果相关文档,可以忽略这个信号。
  • SIGSYS,系统调用异常。
  • SIGKILL,此信号表示系统中止进程。崩溃报告会包含代表中止原因的编码。exit(), kill(9) 等函数调用。iOS 系统杀进程,如 watchDog 杀进程。
  • SIGTRAP,断点指令或者其他trap指令产生。

当我们拦截信号处理之后是可以让程序不崩溃而继续运行的,但是不建议这样做,因为程序已经处于异常不可知状态。
看上图里面最终都会转换为 “UNIX信号”, 是不是代表我们只用监听 “UNIX 信号” 就够了呢?为什么还要拦截 Mach 异常呢?

不是所有的 "Mach异常” 类型都映射到了 “UNIX信号”
“UNIX信号” 在崩溃线程回调,如果遇到 Stackoverflow 问题,已经没有条件(栈空间)再执行回调代码了。

捕获到异常信号后,在处理方法 handleSignalException 里通过 backtrace_symbols 方法就能获取到当前的堆栈信息。
堆栈信息可以先保存在本地,下次启动时再上传到崩溃监控服务器就可以了。

Mach是一个XNU的微内核核心

在这里插入图片描述

3. 崩溃日志包含信息

基本信息:崩溃发生的日期、iOS 版本等
进程信息:崩溃进程的相关信息,比如崩溃报告唯一标识符、唯一键值、设备标识
异常信息:异常类型、异常编码、异常的线程;
线程回溯:崩溃时的方法调用栈

崩溃日志调用栈内容:
在这里插入图片描述
这样直接看崩溃信息的调用栈,是看不懂的

我们需要一个.DSYM文件,dSYM 是保存 函数地址映射信息的中转文件,其中包含文件名、方法名、行号等信息

在这里插入图片描述
一个ipa包,对应一个.DSYM文件

在这里插入图片描述
通过.DSYM文件的解析,就可以找到对应的文件名和函数名

4. 开发中常见崩溃

  • unrecognized selector crash
  • KVO crash
  • NSNotification crash
  • NSTimer crash
  • Container crash(数组越界,插nil等)
  • NSString crash (字符串操作的crash)
  • UI not on Main Thread Crash (非主线程刷UI(机制待改善))

unrecognized selector crash

当一个对象找不到对应的方法实现的时候,会报此类错误

在找不到方法时,查找方法将会进入方法forward流程,系统给了三次补救的机会,
所以我们要解决这个问题,在这三次均可以解决这个问题
在这里插入图片描述

KVO crash

KVO监听对象属性值的改变

KVO 日常使用造成崩溃的原因通常有以下几个:

  • KVO 添加次数和移除次数不匹配:
  • 移除了未注册的观察者,导致崩溃。
  • 重复移除多次,移除次数多于添加次数,导致崩溃。
  • 重复添加多次,虽然不会崩溃,但是发生改变时,也同时会被观察多次。
  • 被观察者提前被释放,被观察者在 dealloc 时仍然注册着 KVO,导致崩溃。

NSNotification crash

当一个对象添加了notification之后,如果dealloc的时候,仍然持有notification,就会出现NSNotification类型的crash。

在iOS9以及iOS9以后,可以不做移除通知操作

NSTimer crash

一般是在定时器被target强引用没有被释放,产生内存泄露,或者在定时器触发的时候导致崩溃
解决方案:
1.NSTimer使用Block,对其target不强引用
2.是否找到一个合适的时机,在确定NSTimer已经失效的情况下,让NSTimer自动invalidate
3.使用中间变量

类族(NSArray,NSMutableArray,NSDictonary,NSMutableDictionary)

  • 插入空对象
  • 数组越界
  • 不可变类型插入数据

建议:

  • 加三目运算符,防止数据为空
  • 数组取值的时候,判断数组个数
  • 遇到可变类型,使用strong修饰

非主线程刷UI

UI刷新,必须在主线程操作
在子线程中,需要刷新UI的时候,要切换到主线程

野指针

在这里插入图片描述

定义:当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称野指针

若操作系统将这部分已经释放的内存重新分配给另外一个进程,而原来的程序重新引用现在的迷途指针,则将产生无法预料的后果。因为此时迷途指针所指向的内存现在包含的已经完全是不同的数据。

在这里插入图片描述

解决方法:

Xcode开启僵尸对象监听
在这里插入图片描述

使用MLeaksFinder或其他三方库,排查内存泄露问题
在这里插入图片描述

使用JJException,减少App闪退
当然,最好做到:开发过程不使用,正式包开启
在这里插入图片描述


参考资料:
iOS 野指针处理
iOS野指针定位总结


Chat-GPT有关野指针的解释

问:iOS野指针错误一般由什么引起的?怎么排查与避免?

答:

iOS 开发中的野指针错误通常是指向一个已经被释放的对象的指针仍然被访问时发生的错误。这种错误可能导致应用崩溃或不稳定的行为。野指针错误的主要原因包括但不限于:

  1. 对象被提前释放:当你尝试访问一个已经被释放的对象时,就会出现野指针错误。这通常是因为对象的引用计数被错误管理,如被提前释放或没有正确地持有对象。
  2. 内存管理不当:在手动管理内存(如使用MRC, 手动引用计数)的项目中,如果没有正确地平衡retain和release调用,可能会导致对象提前释放,从而引发野指针错误。
  3. 指针未初始化或重置:使用未初始化的指针或者在释放对象后未将指针设为nil,也可能导致野指针访问。

如何排查野指针错误:

  1. 使用Xcode的调试工具:利用Xcode的调试工具,如LLDB调试器,可以帮助你定位野指针的来源。Zombies工具尤其有用,它可以帮助追踪已释放对象的访问尝试。
  2. 代码审查:定期进行代码审查可以帮助发现潜在的内存管理错误,特别是对于使用MRC的项目。
  3. 静态分析工具:Xcode自带的静态分析工具可以帮助检测潜在的内存管理问题,包括可能导致野指针错误的情况。

如何避免野指针错误:

  1. 使用自动引用计数(ARC):自动引用计数可以大大减少内存管理错误。确保项目启用ARC,让编译器帮助管理对象的生命周期。
  2. 指针置nil:在释放对象后,将指向该对象的指针置为nil,这样即使尝试访问该指针,也不会导致崩溃。
  3. 避免使用未初始化的指针:在声明指针变量时,初始化为nil,以避免使用未初始化的指针。
  4. 遵循内存管理规则:即使在ARC环境下,也需要理解并遵循基本的内存管理规则,如不要持有非自己创建的对象,除非这个对象已经明确地被retain了。
  5. 使用弱引用:对于不需要拥有对象的引用,使用弱引用可以避免循环引用和提前释放的问题。

通过采取这些措施,你可以显著减少应用中野指针错误的发生,提高应用的稳定性和可靠性。

不得不说,回答的还蛮好的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络原理(3)——TCP协议

目录 一、连接管理 二、三次握手 1、何为三次握手? 2、三次握手有何意义? 三、四次挥手 三次握手和四次挥手的相似之处和不同之处 (1)相似之处 (2)不同之处 四、TCP的状态 建立连接: 断开…

【链表】算法例题

目录 八、 链表 57. 环形链表 ① 58. 两数相加 ② √ 59. 合并两个有序链表 ① √- 60. 随机链表的复制 ② 61. 反转链表II ② 62. K个一组翻转链表 ③ 63. 删除链表的倒数第N个结点 ② √- 64. 删除排序链表中的重复元素II ② √- 65. 旋转链表 ② √- 66. 分隔链…

安科瑞精密配电柜助力数据中心节能降耗

彭姝麟 Acrelpsl 1.趋势分析 能源支出作为数据中心运营的主要成本之一。清华大学能源互联网创新研究院常务副院长高文胜曾在公开场合指出,随着我国数据中心能源消耗的逐年攀升,电费支出约占数据中心年运营成本的95%。加之“双碳”战略的出台&#xff0c…

SkyWalking上报Java应用数据

重要 本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。 通过SkyWalking为应用埋点并上报链路数据至可观测链路 OpenTelemetry 版后,可观测链路 OpenTelemetry 版即可开始监控应用,您可以…

cyclictest 交叉编译报错---rt_numa.h:18:10: fatal error: numa.h: 没有那个文件或目录

cyclictest 主要是用于测试系统延时,进而判断系统的实时性 使用版本 rt-tests-2.6.tar.gz numactl v2.0.16 问题 编译时,需要先编译 numactl ,不然会有以下报错: arm-linux-gnueabihf-gcc -D VERSION2.6 -c src/cyclictest/c…

软考 网工 每日学习打卡 2024/3/19

学习内容 第8章 网络安全 本章主要讲解网络安全方面的基础知识和应用技术。针对考试应该掌握诸如数据加密、报文认 证、数字签名等基本理论,在此基础上深入理解网络安全协议的工作原理,并能够针对具体的 网络系统设计和实现简单的安全解决方案。 本章共有…

Day22初识集合

Day22初识集合 一、集合 1、概念: 集合是指将多个元素组合在一起的数据结构。在编程中,集合用于存储和操作一组相关的数据对象。与数组相比,集合具有更灵活、动态和高级的功能。 2、常见的集合类: List(列表&#x…

sentry-cli - error: Failed to load .sentryclirc file from project path

Xcode 15.2 warning sentry-cli - error: Failed to load .sentryclirc file from project path (/Users/zhuhongwei/Desktop/pandabill/.sentryclirc)推荐一下刚上线的 App 熊猫小账本,里面有用到这篇博客讲的内容 熊猫小账本 一个简洁的记账 App,用于…

1、鸿蒙学习-为应用/服务进行签名

针对应用/服务的签名,DevEco Studio为开发者提供了自动签名方案,帮助开发者高效进行调试。也可选择手动方式对应用/服务进行签名,如果使用了需要ACL的权限,需采用手动方式进行签名。 自动签名 说明 使用自动签名前,请…

闭包机制的底层实现原理

说明:此次分享不涉及ES6的let,const,块级作用域,这些其实都是对本次分享内容的扩展。 闭包的重要性 JS的内功心法,闭包是JavaScript中非常重要的核心概念,关系着JS里很多核心的机制,理解了它,很多问题都会迎刃而解,不理解闭包用JS永远像隔着一层窗户纸。 前端发展日新…

【MySQL】学习和总结使用列子查询查询员工工资信息

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-5odctDvQ0AHJJc1C {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

中国(京津冀)太阳能光伏推进大会暨展览会

中国(京津冀)太阳能光伏推进大会暨展览会是一个旨在促进太阳能光伏产业的发展的重要活动。该活动旨在加大对太阳能光伏的投资和支持,推动太阳能光伏技术的创新和应用,促进太阳能光伏产业的规模化发展。 此次大会暨展览会将为太阳能光伏行业相关企业提供一…

【Linux】Linux基本开发工具(yum) (vi/vim)的使用

本文章内容: 学习yum工具,进行软件安装掌握vim编辑器使用 Linux 软件包管理器 yum 什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序.但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成…

es 聚合操作(一)

前言 Elasticsearch除搜索以外,提供了针对ES 数据进行统计分析的功能。聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如: 衣服品牌的受欢迎程度这些衣服的平均价格、最高价格、最低价格这些衣服的每天、每月销量如何 使用…

产品推荐 | 基于Xilinx Zynq UltraScale+打造的仙女座 Andromeda FPGA核心板

1、产品概述 仙女座Andromeda XZU65片上系统(SoC)核心板通过结合高端Xilinx Zynq UltraScale™ MPSoC系列芯片和高速DDR4 ECC SDRAM、eMMC flash、双QSPI flash、双Gigabit Ethernet PHY、USB 3.0形成了一个完整的、功能强大的嵌入式处理系统。得益于大…

Rhino与Revit API之间的转换

你好,我是九哥~ 最近发现Rhino.Inside.Revit的API手册更新了,终于可以开心的写RIR代码了,小伙伴快去试试吧,地址如下: https://www.rhino3d.com/inside/revit/1.0/reference/rir-api 今天我们先来聊聊 Rhino 与 Rev…

华为ensp中rip动态路由协议原理及配置命令(详解)

CSDN 成就一亿技术人! 作者主页:点击! ENSP专栏:点击! CSDN 成就一亿技术人! ————前言————— RIP(Routing Information Protocol,路由信息协议)是一种距离矢…

xss.pwnfunction(DOM型XSS)靶场

环境进入该网站 Challenges (pwnfunction.com) 第一关&#xff1a;Ma Spaghet! 源码&#xff1a; <!-- Challenge --> <h2 id"spaghet"></h2> <script>spaghet.innerHTML (new URL(location).searchParams.get(somebody) || "Somebo…

YOLO_you only look once

前言 计算机图形学的课程即将结束&#xff0c;我需要提交一份关于YOLO模型的学习报告。在这段时间里&#xff0c;我对YOLO进行了深入的学习和研究&#xff0c;并记录下了我的学习过程和心得体会。本文将详细介绍YOLO模型的原理、优缺点以及应用领域&#xff0c;希望能够为后续…