首先,安利一个facebook的调试神器: Chisel 。
Xcode动态调试原理:
首先来了解几个术语:GCC,LLVM,GDB,LLDB:GCC和GDB属于编译器,LLVM和LLDB属于调试器
- Xcode编译器的发展历程:GCC —> LLVM
- Xcode调试器的发展历程:GDB —> LLDB
当Xcode识别到手机设备后,会自动将debugserver安装到iPhone上面:/Developer/usr/bin/debugserver。之后Xcode利用本身集成的调试器LLDB和debugserver交互,达到调试APP的目的。
LLDB常用命令:
首先介绍下lldb命令的格式:
-
help:
help:只输入help会列出lldb的所有命令,包括用户自定义的lldb命令集
help <command>: 某个命令的用法信息,比如help breakpoint
help <command> [subcommand] : 某个命令的子命令的用法,比如help breakpoint set
-
p、call、print、express四个命令等价,都是可以执行一个表达式
比如
可以p self.xxx来获取某个属性值
可以p self.view.backgroundColor = [UIColor redColor],这样就可以随心所欲的执行自己想要的代码,免去反复的build操作
-
po
po和p的一个差别是p命令只能拿到对象的内存地址,po可以取得对象更详细的信息:比如NSArray和NSDictionary会打印内部的元素,UIVeiw会打印frame,layer等信息
-
thread backtrace : 快捷键bt
打印线程的堆栈信息
-
thread return [<expr>]:直接退出当前的函数调用栈
-
thread continue、continue、c :程序继续运行
-
thread stepover、next、n:单步运行,把子函数当做一个整体
-
thread step-in、step、s:单步运行,遇到子函数会跳进子函数
-
thread step-out、finish:执行完当前函数的所有代码,返回到上一个调用的函数
-
watchpoint set variable 变量:当内存数据变化时触发断点
-
watchpoint list:列出内存断点列表
-
watchpoint enable 断点编号:使能断点
-
watchpoint disable 断点编号:使断点失效
-
watchpoint delete 断点编号:删除断点
-
image lookup -address 内存地址:查找这个地址具体对应的文件位置
-
image lookup -name methodName: 查找一个方法或者符号的信息,比如所在文件位置等
-
image lookup -type className :打印某个类的信息
更多的lldb命令请参考官方文档:文档
lldb汇编层面常用调试命令
-
register read 读取所以寄存器的值
-
register write w0 0x8 把值写进寄存器
-
x命令读取内存内容
命令格式:x/nfu obj
n:代表要读取几个单元
f:显示方式,有如下值
参数 含义 x 按十六进制格式显示变量 d 按十进制格式显示变量 u 按十进制格式显示无符号整型 o 按八进制格式显示变量 t 按二进制格式显示变量 a 按十六进制格式显示变量 i 指令地址格式 c 按字符格式显示变量 f 按浮点数格式显示变量 u:表示一个单元的长度
参数 含义 b 按单字节分段输出 h 按双字节分段输出 w 按四字节分段输出 g 按八字节分段输出 obj:表示内存地址,可以是变量名,也可以是内存地址。
Chisel
Chisel是facebook开源的辅助动态调试iOS APP的LLDB命令集合。详细文档参考 github wiki
下面我举几个比较常用:
-
bmessage:这个命令可以指定某个方法打断点,即使你的代码没有重写这个方法,bmessage也会遍历继承链去查找。
用法: bmessage -[ViewController viewWillAppear:]
-
border:给指定的view添加边框
用法:border -c red -w 5 self.redView 或者 border --color=red —width=5 self.redView
等价于lldb命令:p self.redView.layer.borderColor = [UIColor redColor].CGColor && p self.redView.layer.borderWidth = 5
怎么样?是不是爽多了!
-
unborder:去除view的边框。
-
caflush:重新刷新UI界面
-
flicker:闪烁指定的view,可以快速定位到指定view的位置
-
fv: fv <classNameRegex>,指定一个ClassName的正则表达式,fv会打印出整个视图层级中subview的类名符合正则表达式的对象
-
fvc:fvc [--name=classNameRegex] [--view=view],两个参数只能指定其中一个。根据类名或者指定view来查找对应的控制器实例对象。
-
hide & show:显示或隐藏指定的view
-
mwarning:模拟发出一个内存警告
-
pbundlepath:打印budler路径
-
pdocspath:打印沙盒路径。pdocspath -o,打印路径的同时在Finder中打开
-
pinternals:打印对象内部的成员变量
-
pjson:打印json数据,lldb的po指令显示不了中文,pjson可以显示中文
-
pmethods:打印某个类的方法
用法:pmethods -a -i -c -n IndexMainController (-a:把方法函数指针打印出来,-i:打印实例方法,-c:打印类方法)
-
pvc:打印当前控制器的层级结构
-
pviews:pviews self.view: 打印self.view的subviews
-
slowanim && unslowanim:这两个命令在调试动画的时候非常。有用用法:slowanim <speed>,speed默认是0.1。
-
taplog:输入taplog,然后点击屏幕上面的view,会把这个view的信息打印出来
-
visualize:visualize <target> (target可以是: UIImage, CGImageRef, UIView, or CALayer),调用系统的图片查看器展示对应的对象。
网友评论