内容简介:在iOS项目开发过程中,常用到静态分析(Analyze)、断点(BreakPoint)和控制台(Console)进行代码调试。本篇文章介绍Xcode常用调试方法之”LLDB命令“。本文来自360奇舞团QiShare团队投稿。
在iOS项目开发过程中,常用到静态分析(Analyze)、断点(BreakPoint)和控制台(Console)进行代码调试。本篇文章介绍Xcode常用调试方法之”LLDB命令“。
本文来自360奇舞团QiShare团队投稿。
相关阅读:
- 《 iOS 常用调试方法:静态分析 》
- 《 iOS 常用调试方法:断点调试 》
简介
LLDB是新一代高性能调试器。它构建为一组可重用的组件,可以高度利用较大的LLVM项目中的现有库,例如Clang表达式解析器和LLVM反汇编程序。
LLDB是Mac OS X上Xcode的默认调试器,支持在桌面和iOS设备和模拟器上调试C,Objective-C和C ++。
LLDB项目中的所有代码都是在标准LLVM许可证下提供的,这是一种开源的“BSD风格”许可证。
帮助
LLDB命令格式如下:
<命令名称> <命令动作> [-可选项 [可选项的值]] [参数1 [参数2...]]
LLDB命令的各部分由空格分割,如果参数中包含空格,则需要使用双引号括起参数,如果参数中包含双引号或者反斜杠,则需要使用反斜杠进行转义。
LLDB命令有非常多的功能,完全背下来不太容易,也没必要。开发者可以使用help命令查看相关命令的用法,甚至可以查看help命令的用法。
(lldb) help help Show a list of all debugger commands, or give details about a specific command. Syntax: help [<cmd-name>] Command Options Usage: help [-ahu] [<cmd-name> [<cmd-name> [...]]] -a ( --hide-aliases ) Hide aliases in the command list. -h ( --show-hidden-commands ) Include commands prefixed with an underscore. -u ( --hide-user-commands ) Hide user-defined commands from the list. This command takes options and free-form arguments. If your arguments resemble option specifiers (i.e., they start with a - or --), you must use ' -- ' between the end of the command options and the beginning of the arguments.
3. 执行
在LLDB中,执行命令expression是最基础的命令,简写为expr或者e,语法为:expression
//! 输出count的值 (lldb) expression count (NSUInteger) $0 = 10 //! 执行string的拼接字符串方法 (lldb) expression [string stringByAppendingString:@"732"] (__NSCFString *) $1 = 0x00006000006ac870 @"QiShare732" //! 修改view的颜色 (lldb) expression self.view.backgroundColor = [UIColor redColor] (UICachedDeviceRGBColor *) $2 = 0x0000600001d74780 (lldb) expression [CATransaction flush] //!< 因为断点会终止UI线程,执行[CATransaction flush]命令可以渲染出修改后的界面
4. 打印
打印命令print是最常用的命令,简写为pri或者p,语法为:print
同样常用的expression简写命令还有po和call。其中po表示print object,用来打印对象,call用来调用某个方法。示例如下:
(lldb) expression -- self.view (UIView *) $4 = 0x00007f8ca8401690 (lldb) e self.view (UIView *) $5 = 0x00007f8ca8401690 (lldb) p self.view (UIView *) $6 = 0x00007f8ca8401690 (lldb) po self.view <UIView: 0x7f8ca8401690; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x6000008a1dc0>> (lldb) call self.view (UIView *) $8 = 0x00007f8ca8401690
另外,开发者可以按照print/
p/x //!< 以十六进制打印整数 p/d //!< 以带符号的十进制打印整数 p/u //!< 以无符号的十进制打印整数 p/o //!< 以八进制打印整数 p/t //!< 以二进制打印整数 p/a //!< 以十六进制打印地址 p/c //!< 打印字符常量 p/f //!< 打印浮点数 p/s //!< 打印字符串 p/r //!< 格式化打印
p/x //!< 以十六进制打印整数p/d //!< 以带符号的十进制打印整数p/u //!< 以无符号的十进制打印整数p/o //!< 以八进制打印整数p/t //!< 以二进制打印整数p/a //!< 以十六进制打印地址p/c //!< 打印字符常量p/f //!< 打印浮点数p/s //!< 打印字符串p/r //!< 格式化打印
示例如下:
(lldb) p count (NSUInteger) $0 = 10 (lldb) p/t count (NSUInteger) $1 = 0b0000000000000000000000000000000000000000000000000000000000001010 (lldb) p/o count (NSUInteger) $2 = 012 (lldb) p/x count (NSUInteger) $3 = 0x000000000000000a (lldb) p/x string (__NSCFConstantString *) $4 = 0x000000010416a0b8 @"QiShare" (lldb) p/c string (__NSCFConstantString *) $5 = \xb8\xa0\x16\x04\x01\0\0\0 @"QiShare" (lldb) p/s string (__NSCFConstantString *) $6 = @"QiShare" (lldb) p/a string (__NSCFConstantString *) $7 = 0x000000010416a0b8 @"QiShare" @"QiShare"
5. 线程
thread是线程相关的命令,语法为thread
开发者可以使用thread list命令查看当前的所有线程,示例如下:
(lldb) thread list Process 4031 stopped * thread #1: tid = 0x25cac, 0x0000000104167e23 QiDebugDemo`-[QiConsoleViewController testLLDBCommands](self=0x00007f850df0bbf0, _cmd="testLLDBCommands") at QiConsoleViewController.m:34, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1 thread #2: tid = 0x25d2f, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 thread #3: tid = 0x25d30, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 thread #4: tid = 0x25d31, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 thread #5: tid = 0x25d32, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 thread #6: tid = 0x25d33, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 thread #7: tid = 0x25d3e, 0x00000001079f520a libsystem_kernel.dylib`mach_msg_trap + 10, name = 'com.apple.uikit.eventfetch-thread'
thread backtrace命令可以方便地供开发者查看线程堆栈信息,简写为bt。比如,当程序崩溃的时候,开发者可以查看堆栈调用列表。示例如下:
(lldb) thread backtrace * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x0000000104cc2705 libobjc.A.dylib`objc_exception_throw frame #1: 0x00000001056704ec CoreFoundation`_CFThrowFormattedException + 194 frame #2: 0x00000001057a6b00 CoreFoundation`-[__NSArrayI objectAtIndexedSubscript:] + 96 * frame #3: 0x00000001043a1df7 QiDebugDemo`-[QiConsoleViewController testLLDBCommands](self=0x00007fadc7c50400, _cmd="testLLDBCommands") at QiConsoleViewController.m:33 frame #4: 0x00000001043a1d5a QiDebugDemo`-[QiConsoleViewController viewDidLoad](self=0x00007fadc7c50400, _cmd="viewDidLoad") at QiConsoleViewController.m:26 ... frame #18: 0x00000001056830be CoreFoundation`__CFRunLoopDoObservers + 430 frame #19: 0x0000000105683751 CoreFoundation`__CFRunLoopRun + 1537 frame #20: 0x0000000105682e11 CoreFoundation`CFRunLoopRunSpecific + 625 frame #21: 0x000000010ddd51dd GraphicsServices`GSEventRunModal + 62 frame #22: 0x000000010a1db81d UIKitCore`UIApplicationMain + 140 frame #23: 0x00000001043a2450 QiDebugDemo`main(argc=1, argv=0x00007ffeeb85df90) at main.m:7 frame #24: 0x0000000107858575 libdyld.dylib`start + 1
在调试过程中,开发者可以使用thread return命令终端某个方法并返回一个想要的值。示例如下:
(lldb) thread return string (lldb) continue 2019-02-27 17:22:47.323225+0800 QiDebugDemo[5071:222700] resultString: Qi_Share
6. 断点
作者在iOS 调试方法:断点这篇文章中介绍过断点的用法。其实,可视化的断点都可以使用LLDB语法来实现。比如下图中的1、2、3、4、5都能用LLDB命令表达。
- 启用/禁用断点(breakpoint enable/disable)
- 继续执行程序(continue)
- 执行下一步(next)
- 进入方法(step)
- 跳出方法(finish)
在断点相关操作中,因为Xcode已经集成了可视化的断点操作工具,所以breakpoint命令并不被常用。但是,breakpoint命令拥有着十分强大的功能,语法为:breakpoint
//! 查看所有断点 (lldb) breakpoint list //! 为所有类中的viewDidAppear:设置断点 (lldb) breakpoint set -n viewDidAppear: //! 为QiConsoleViewController.m文件中的testLLDBCommands方法设定断点 (lldb) breakpoint set -f QiConsoleViewController.m -n testLLDBCommands //! 为QiConsoleViewController.m文件中的第32行代码设定断点 (lldb) breakpoint set -f QiConsoleViewController.m -l 32 //! 为handleString:方法设定条件断点,条件为string != nil (lldb) breakpoint set - handleString: -c string != nil
7. 观察点
想比较于breakpoint是对方法生效的断点,watchpoint则是对地址生效的断点。watchpoint类似于KVO的工作原理,当观察到属性地址里面的东西改变时,就让程序中断,其语法为:watchpoint
(lldb) watchpoint set variable string Watchpoint created: Watchpoint 1: addr = 0x7ffeef497360 size = 8 state = enabled type = w declare @ '/Users/huangxianshuai/Desktop/Products/QiShare/QiDebugDemo/QiDebugDemo/QiConsoleViewController.m:33' watchpoint spec = 'string' new value: 0x00000001007670b8 (lldb) next Watchpoint 1 hit: old value: 0x00000001007670b8 new value: 0x0000000100767138 (lldb) image lookup -a 0x00000001007670b8 Address: QiDebugDemo[0x00000001000040b8] (QiDebugDemo.__DATA.__cfstring + 32) Summary: @"QiShare" (lldb) image lookup -a 0x0000000100767138 Address: QiDebugDemo[0x0000000100004138] (QiDebugDemo.__DATA.__cfstring + 160) Summary: @"huang"
image lookup -a 是 image lookup -address 的简写,可以查看参数地址的内容。
8. 总结
文章仅列举了作者平常使用到的一些LLDB命令,这些命令的确能提高调试效率。而更多的LLDB命令可以从LLDB Homepage( http://lldb.llvm.org /)或者其他网络资源中获取。
【本文是51CTO专栏机构360技术的原创文章,微信公众号“360技术( id: qihoo_tech)”】
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用 expression 命令调试 UI 问题
- iOS 常用调试方法:LLDB命令
- Wuzz 0.4.0 发布,HTTP 命令行调试工具
- LWN: 想用python命令来调试kernel吗?drgn就是了!
- 使用 dotnet 命令行配合 vscode 完成一个完整 .NET 解决方案的编写和调试
- iOS常用调试方法:断点调试
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Book of CSS3
Peter Gasston / No Starch Press / 2011-5-13 / USD 34.95
CSS3 is the technology behind most of the eye-catching visuals on the Web today, but the official documentation can be dry and hard to follow. Luckily, The Book of CSS3 distills the heady technical la......一起来看看 《The Book of CSS3》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
HEX HSV 转换工具
HEX HSV 互换工具