iOS开发调试概览
作者:@KenshinCui
本文为作者原创,转载请注明出处:https://www.cnblogs.com/kenshincui/p/11953536.html
目录
我们都知道Xcode默认的调试器是LLDB(在此之前使用的是
关于更多lldb命令的说明,一个简单额技巧是直接输入help ,另外有时会可能会遇到无法打印变量,可以看一下SWIFT_OPTIMIZATION_LEVEL,当然如果你在一个block内打印一个外部变量因为默认并不会捕获这个变量所以也应该无法打印此值。
frame
frame用于查看当前栈帧信息(栈上面的函数调用内存片段),比如说frame info
就会打印当前所在函数、行数和所在文件等信息。
frame variable
:查看当前栈帧中的变量(包括外部全局变量,当然如果只想要看当前文件中的全局变量使用 target variable = ta v
)frame variable x = fr v x = v x
:查看当前栈帧中的变量值(如果配合-L
参数可以查看一个变量的内存地址),但是不同于expression的是frame variable仅仅是查看当前栈帧中的实际存储变量,如swift中的一个计算变量它是没办法看到的,因为它的运行原理并不是像expression一样会在一个context中执行相关的代码进行结果输出。
watchpoint
除了breakpoint之外watchpoint应该是一种比较常用的内存访问断点机制,有时会随着界面越来越复杂,有些变量可能会在多处修改造成看起来你的修改并不能达到你理解的目的,这时如果使用watchpoint监控所有的修改甚至读取就比较有用了。watchpoint使用有两种方式:
watchpoint set variable
:监听一个变量的变化watchpoint set expression
:通过一个表达式为一个地址添加断点
比如说:watchpoint set variable self.isLoad
(假设isLoad是VC中一个标记viewDidLoad()
是否执行过的标记),此当可以看到输出:Watchpoint created: Watchpoint 1: addr = 0x100a04500 size = 1 state = enabled type = w declare @ '/Users/cuijiangtao/Library/Mobile Documents/com.apple.CloudDocs/XcodeDebug/XcodeDebug/ViewController.swift:73' watchpoint spec = 'self.isLoad' new value: false watchpoint set variable self.isLoad
一旦self.isLoad被修改则会命中断点,同时输出:Watchpoint 1 hit: old value: false new value: true
但是到了这里可能我们还会遇到一种情况是如果要是想要监听一个控件的属性修改怎么办呢,可以试一下用上面的方法watchpoint set variable subview1.frame
(subview1是某个UIView类型的属性)应该会提示没有frame属性。常用的方式可以通过断点到一个UIView的setFrame方法上(注意:这里的语法是OC,即使在swift环境中),比如:breakpoint set -F '-[UIView setBounds:]' -c '((int*)$esp)[1] == 0x10131e440'
当然这里最主要是还是获取寄存器索引和对应UIView的地址,可以使用:po self.view
。
注意在Xcode的variable面板其实右键也可以监控某个变量状态,甚至可以查看其内存。
thread backtrace
显示程序停止在breakpoint前当前线程所有帧,用于追踪调用堆栈信息。值得一提的是类似功能的还有bt
,它并非thread backtrace的简写(如果是简写应该是tb才对吧)而是_regexp-bt
简写。
image(target modules)
借助image我们能够查看当前的Binary Images相关的信息,日常开发我们主要利用它寻址。比如有了栈地址通过image lookup -a xxx
即可查找到具体执行的位置。