iOS常见崩溃简介

news2024/11/24 15:37:19

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.coloradmin.cn/o/1531650.html

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

相关文章

全网最详细介绍如何实现图片存储阿里OSS实现资源持久化存储

什么是阿里云OSS 阿里云OSS(Object Storage Service,对象存储服务)是阿里云提供的一种存储服务,它支持任意类型的数据存储,如图片、视频、日志文件等。OSS以对象(Object)的形式组织数据&#x…

【导论】数据可信流通 从运维信任到技术信任

信任 信任概念由于其抽象性和结构复杂性,在社会学、心理学、营销学、经济学、管理学等不同 的领域定义是不同的,但是达成共识的观点是:信任是涉及交易或交换关系的基础。 信任的基石 ①身份可确认,②利益可依赖,③能…

docker实战(3)

1, jdk17版本的dockerfile FROM eclipse-temurin:17-jre ADD ./target/ods-poc-0.0.1-SNAPSHOT.jar /home/app/app.jar WORKDIR /home/app ENV TZ Asia/Shanghai ENTRYPOINT ["java","-jar","/home/app/app.jar"] EXPOSE 8083dockerfile 1, …

数据结构的概念大合集02(线性表)

概念大合集02 1、线性表及其逻辑结构1.1 线性表的定义1.2 线性表的基本操作 2、线性表的顺序存储结构2.1 顺序表 3、线性表的链式存储3.1 链表3.1.1 头结点(头指针),首指针,尾指针,尾结点3.1.2 单链表3.1.3 双链表3.1.…

Linux第79步_使用自旋锁保护某个全局变量来实现“互斥访问”共享资源

自旋锁使用注意事项:自旋锁保护的“临界区”要尽可能的短。 因此,在open()函数中申请“spinlock_t自旋锁结构变量”,然后在release()函数中释放“spinlock_t自旋锁结构变量”,这种方法就行不通了。如果使用一个变量“dev_stats”来表示“共享…

Nanya(南亚科技)DRAM芯片选型详解

一、DRAM产品选型 普通SDRAM只在时钟的上升期进行数据传输,DDR内存能够在时钟的上升期和下降期各传输一次数据,因此性能翻倍,被称为双倍速率同步动态随机存储器。因此DDR内存可以在与SDRAM相同的总线频率下达到更高的数据传输率。DDR是一种掉…

Pygame AttributeError no attribute ‘display‘问题及其解决方法

目录 前言 错误原因 解决方法 1. 确保正确安装 Pygame 2. 检查 Python 路径和 Pygame 模块位置 3. 修复模块命名冲突 4. 检查代码错误 5. 检查 Pygame 版本兼容性 代码示例 总结 前言 Pygame 是一个非常受欢迎的 Python 游戏开发库,它提供了丰富的功能和…

Linux 学习必备:CentOS 技能提升一站式平台!

介绍:CentOS是一种广泛使用的Linux发行版,特别受到企业用户的青睐。 首先,CentOS的全称是Community Enterprise Operating System,中文意思是“社区企业操作系统”。它起源于Red Hat Enterprise Linux (RHEL)的源代码,…

极智压缩 ——帮你高清无损压缩 JPG/PNG/GIF 图片!

引言 图片太大怎么办?图片该如何压缩?压缩后图片为什么变模糊了?屏幕前的你是不是经常被这些问题所困扰,腾讯云数据万象推出的图片极智压缩服务,可以帮你高清无损压缩 JPG/PNG/GIF 图片,解决你95%以上的图片…

解决虚拟机Linux ens33 没有 IP 地址

解决方法: 先进入 root 模式 sudo su 查看目录 ls /etc/sysconfig 找到上述文件夹 ls /etc/sysconfig/network-scripts/ 用 vim 打开 ifcfg-ens33 这个文件(不都是这个名字,按这个方法找到这个文件就行) vim /etc/sysconfig/netw…

学习笔记-华为IPD转型2020:3,IPD的实施

3. IPD的实施 1999 年开始的 IPD 转型是计划中的多个转型项目中的第一个(Liu,2015)。华为为此次转型成立了一个专门的团队,从大约20人开始,他们是华为第一产业的高层领导。董事会主席孙雅芳是这个团队的负责人。该团…

【算法与数据结构】深入二叉树实现超详解

文章目录 📝前言🌠 接口函数✏️ 实现函数🌉创建树的新节点🌠通过前序遍历的数组构建二叉树🌉包装通过前序遍历的数组构建二叉树🌠二叉树的销毁🌠层次遍历🌠第一种实现:不…

如何在尽量不损害画质的前提下降低视频占内存大小?视频格式科普及无损压缩软件推荐

大家好呀,相比大家都有对视频画质和体积的追求和取舍,那么,如何才能在不牺牲画质的前提下,尽可能的将视频大小降低到极致呢? 首先我们要了解视频的构成,要想降低视频的体积大小,我们可以从以下几…

Learn OpenGL 22 高级光照与Gamma校正

高级光照 Blinn-Phong 冯氏光照不仅对真实光照有很好的近似,而且性能也很高。但是它的镜面反射会在一些情况下出现问题,特别是物体反光度很低时,会导致大片(粗糙的)高光区域。下面这张图展示了当反光度为1.0时地板会…

品牌方年度抖音店铺打造流量运营孵化方案

【干货资料持续更新,以防走丢】 品牌方年度抖音店铺打造流量运营孵化方案 部分资料预览 资料部分是网络整理,仅供学习参考。 PDF共120页(完整资料包含以下内容) 目录 抖音年度短视频直播运营规划方案 1. 帐号视频发布规划 问…

55、服务攻防——数据库安全RedisHadoopMysql未授权访问RCE

文章目录 常见服务应用的安全测试: 配置不当——未授权访问安全机制——特定安全漏洞安全机制——弱口令爆破攻击 应用服务安全测试流程: 判断服务开放情况——端口扫描&组合猜解等 端口扫描:服务开放,绑定端口没开放&#…

浅谈前端路由原理hash和history

1、认识前端路由 本质 前端路由的本质,是监听 url 地址或 hash 值的改变,来切换渲染对应的页面组件 前端路由分为两种模式 hash 模式 history 模式 两种模式的对比 2、hash 模式 (1)hash 定义 hash 模式是一种把前端路由的路…

管理类联考–复试–英文面试–问题--规划介绍原因做法--纯英文版

借鉴 https://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.clickhttps://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.click https://ttsreader.com/zh/https://ttsreader.com/zh/ 规划 视频版…

MyBatis3源码深度解析(十七)MyBatis缓存(一)一级缓存和二级缓存的实现原理

文章目录 前言第六章 MyBatis缓存6.1 MyBatis缓存实现类6.2 MyBatis一级缓存实现原理6.2.1 一级缓存在查询时的使用6.2.2 一级缓存在更新时的清空 6.3 MyBatis二级缓存的实现原理6.3.1 实现的二级缓存的Executor类型6.3.2 二级缓存在查询时使用6.3.3 二级缓存在更新时清空 前言…