【iOS内功】深入解析Crash调用栈的内存布局

·  阅读 1756
【iOS内功】深入解析Crash调用栈的内存布局

一、栈的基础概念

栈是一种数据结构,只能在”一端”进行”插入”和”删除”的线性表。其中能进行插入和删除的这一端就是“栈顶”,另外一端称为“栈底”。

栈的模型

程序员说的栈经常默认指的是内存中的栈,但栈是一个基础的数据结构,不局限在计算机,其他领域都可以见到栈的应用。

比如码头对货柜箱的存储,货车来了,一个一个箱子叠起来就是在入栈,船来了,一个个箱子从上往下搬走,就是在出栈,地面就是栈底,最高的位置就只栈顶。

二、栈在内存如何布局

上面是常规的栈的模型,栈顶在上面,栈底在下面。但是在内存中,栈的布局刚好“相反”,栈顶在下面,栈底在下面。

内存有N个GB大小,以字节为单位进行划分,为了方便寻址,按顺序给每一个字节编号,这个编号我们称为内存地址。地址数值小的我们称为低地址0x000000001,数值大的们称为高地址0xc00000000。

而栈在内存中是从高地址到低地址的,一般用图来描述内存地址布局,高地址会在上面,低地址会在下面,所以从图中看栈底在上面,栈顶在下面。

注:栈为什么在内存中是从高地址到低地址生长(思考题)
复制代码

栈的内存布局模型

三、调用栈

什么是调用栈?

一个线程里的函数调用的序列,使用栈的数据结构存储,这就是调用栈。 首现要理解线程的概念。线程是操作系统能够调度的最小的执行体,它是一个单一顺序的控制流,CPU在同一时间只会处理一个线程的任务。

CPU支持多线程处理,每次切换线程要先切换线程的上下文。上下文包括寄存器的数据,堆栈中存储的数据。包括局部变量、当前执行的代码地址、中间变量等。

CPU要执行的线程任务,可以理解为按顺序调用的方法树,方法里面会嵌套子方法,子方法就是树的子节点。

iOS运行时,如果出现Crash,可以通过 “[NSThread callStackSymbols]”抓取当前线程的调用栈。

Thread 17 Crashed:
0   libGPUSupportMercury.dylib      0x000000022d873fe4 _gpus_ReturnNotPermittedKillClient
1   AGXGLDriver                     0x0000000231f21ed8 0x0000000231efd000 + 151256
2   libGPUSupportMercury.dylib      0x000000022d874fac _gpusSubmitDataBuffers
复制代码

这个调用栈是方法的回溯,序号0是发生异常的最后一个方法,序号1是调用序号0的方法,依次类推往回溯源。有了回溯的线程调用栈,我们就可以排查Crash的源头在哪里。

线程调用栈在内存中如何布局

上面的线程调用栈,是由高级语言(OC、C、C++、swift)的函数调用符号(Symbol)组成。在高级语言层面分析,我们可以定位到80%Crash的原因。

而20%的疑难杂症需要进入到汇编层面来分析,因此我们要掌握CPU在执行一个线程任务时,调用栈在内存是如何布局的。

我们不需要考虑多线程,多线程切换会伴随上线文的切换,同一时间只需要考虑一个线程调用栈。

注:iOS程序只需要掌握ARM64汇编
注:ARM64汇编(知识点)
复制代码

OC函数使用LLVM编译成ARM汇编语言后,是多个汇编指令。Arm汇编以函数为单位来布局指令,调用另外一个函数使用跳转指令bl,函数执行完要使用ret指令返回上一个函数。

CPU在执行指令时,会将一个函数映射会一个栈桢(stack frame),栈桢相当于一个嵌套在当前线程调用栈中的子栈,FP寄存器指向栈桢的栈底,SP寄存器指向栈桢的栈顶。

栈桢布局模型

栈桢(Stack Frame)

Stack Frame是一个按照方法调用顺序, 从栈的高地址向低地址依次存放的一组数据, 用于存放上一次方法调用的关键信息.它是一个函数所使用的stack的一部分,所有函数的stack frame串起来就组成了一个完整的栈。

参考

FP寄存器及frame pointer介绍

ARM64 Function Calling Conventions

Stack Frames

Procedure Call Standard for the ARM 64-bit Architecture (AArch64)

ARM Reference Manual:

文章汇总

iOS内功系列

【iOS内功】Crash分析模型

【iOS内功】深入解析Crash调用栈的内存布局

【iOS内功】ARM黑魔法—栈桢的入栈和出栈

【iOS内功】使用Hopper定位疑难问题

架构系列

架构师常说的“技术架构”是指什么?

如何系统建设APP稳定性?

思维系列

高绩效工程师的“工作思维模型”

分类:
iOS
标签:
分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改