自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS常用調(diào)試方法:LLDB命令

開發(fā) 開發(fā)工具 前端 移動開發(fā)
在iOS項目開發(fā)過程中,常用到靜態(tài)分析(Analyze)、斷點(BreakPoint)和控制臺(Console)進行代碼調(diào)試。本篇文章介紹Xcode常用調(diào)試方法之”LLDB命令“。

在iOS項目開發(fā)過程中,常用到靜態(tài)分析(Analyze)、斷點(BreakPoint)和控制臺(Console)進行代碼調(diào)試。本篇文章介紹Xcode常用調(diào)試方法之”LLDB命令“。

本文來自360奇舞團QiShare團隊投稿。

[[263601]]

相關(guān)閱讀:

1.簡介

LLDB是新一代高性能調(diào)試器。它構(gòu)建為一組可重用的組件,可以高度利用較大的LLVM項目中的現(xiàn)有庫,例如Clang表達式解析器和LLVM反匯編程序。

LLDB是Mac OS X上Xcode的默認調(diào)試器,支持在桌面和iOS設(shè)備和模擬器上調(diào)試C,Objective-C和C ++。

LLDB項目中的所有代碼都是在標(biāo)準(zhǔn)LLVM許可證下提供的,這是一種開源的“BSD風(fēng)格”許可證。

2.幫助

LLDB命令格式如下:

  1. <命令名稱> <命令動作> [-可選項 [可選項的值]] [參數(shù)1 [參數(shù)2...]] 

LLDB命令的各部分由空格分割,如果參數(shù)中包含空格,則需要使用雙引號括起參數(shù),如果參數(shù)中包含雙引號或者反斜杠,則需要使用反斜杠進行轉(zhuǎn)義。

LLDB命令有非常多的功能,完全背下來不太容易,也沒必要。開發(fā)者可以使用help命令查看相關(guān)命令的用法,甚至可以查看help命令的用法。

  1. (lldb) help help 
  2.      Show a list of all debugger commands, or give details about a specific 
  3.      command. 
  4.  
  5. Syntax: help [<cmd-name>
  6.  
  7. Command Options Usage: 
  8.   help [-ahu] [<cmd-name> [<cmd-name> [...]]] 
  9.  
  10.        -a ( --hide-aliases ) 
  11.             Hide aliases in the command list. 
  12.  
  13.        -h ( --show-hidden-commands ) 
  14.             Include commands prefixed with an underscore. 
  15.  
  16.        -u ( --hide-user-commands ) 
  17.             Hide user-defined commands from the list. 
  18.       
  19.      This command takes options and free-form arguments.  If your arguments 
  20.      resemble option specifiers (i.e., they start with a - or --), you must use 
  21.      ' -- ' between the end of the command options and the beginning of the 
  22.      arguments. 

3. 執(zhí)行

在LLDB中,執(zhí)行命令expression是最基礎(chǔ)的命令,簡寫為expr或者e,語法為:expression -- ,它的作用是執(zhí)行一個表達式,并輸出表達式返回的結(jié)果。示例如下:

  1. //! 輸出count的值 
  2. (lldb) expression count 
  3. (NSUInteger) $0 = 10 
  4.  
  5. //! 執(zhí)行string的拼接字符串方法 
  6. (lldb) expression [string stringByAppendingString:@"732"] 
  7. (__NSCFString *) $1 = 0x00006000006ac870 @"QiShare732" 
  8.  
  9. //! 修改view的顏色 
  10. (lldb) expression self.view.backgroundColor = [UIColor redColor] 
  11. (UICachedDeviceRGBColor *) $2 = 0x0000600001d74780 
  12. (lldb) expression [CATransaction flush] 
  13. //!< 因為斷點會終止UI線程,執(zhí)行[CATransaction flush]命令可以渲染出修改后的界面 

4. 打印

打印命令print是最常用的命令,簡寫為pri或者p,語法為:print ,它的作用是打印變量或者表達式。通過help print會發(fā)現(xiàn)print其實是expression --命令的簡寫:'print' is an abbreviation for 'expression --',其中--標(biāo)識選項的結(jié)束和參數(shù)的開始。

同樣常用的expression簡寫命令還有po和call。其中po表示print object,用來打印對象,call用來調(diào)用某個方法。示例如下:

  1. (lldb) expression -- self.view 
  2. (UIView *) $4 = 0x00007f8ca8401690 
  3.  
  4. (lldb) e self.view 
  5. (UIView *) $5 = 0x00007f8ca8401690 
  6.  
  7. (lldb) p self.view 
  8. (UIView *) $6 = 0x00007f8ca8401690 
  9.  
  10. (lldb) po self.view 
  11. <UIView: 0x7f8ca8401690; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x6000008a1dc0>> 
  12.  
  13. (lldb) call self.view 
  14. (UIView *) $8 = 0x00007f8ca8401690 

另外,開發(fā)者可以按照print/的語法為print命令指定打印格式:

  1. p/x  //!< 以十六進制打印整數(shù) 
  2. p/d  //!< 以帶符號的十進制打印整數(shù) 
  3. p/u  //!< 以無符號的十進制打印整數(shù) 
  4. p/o  //!< 以八進制打印整數(shù) 
  5. p/t  //!< 以二進制打印整數(shù) 
  6. p/a  //!< 以十六進制打印地址 
  7. p/c  //!< 打印字符常量 
  8. p/f  //!< 打印浮點數(shù) 
  9. p/s  //!< 打印字符串 
  10. p/r  //!< 格式化打印 

p/x //!< 以十六進制打印整數(shù)p/d //!< 以帶符號的十進制打印整數(shù)p/u //!< 以無符號的十進制打印整數(shù)p/o //!< 以八進制打印整數(shù)p/t //!< 以二進制打印整數(shù)p/a //!< 以十六進制打印地址p/c //!< 打印字符常量p/f //!< 打印浮點數(shù)p/s //!< 打印字符串p/r //!< 格式化打印

示例如下:

  1. (lldb) p count 
  2. (NSUInteger) $0 = 10 
  3.  
  4. (lldb) p/t count 
  5. (NSUInteger) $1 = 0b0000000000000000000000000000000000000000000000000000000000001010 
  6.  
  7. (lldb) p/o count 
  8. (NSUInteger) $2 = 012 
  9.  
  10. (lldb) p/x count 
  11. (NSUInteger) $3 = 0x000000000000000a 
  12.  
  13. (lldb) p/x string 
  14. (__NSCFConstantString *) $4 = 0x000000010416a0b8 @"QiShare" 
  15.  
  16. (lldb) p/c string 
  17. (__NSCFConstantString *) $5 = \xb8\xa0\x16\x04\x01\0\0\0 @"QiShare" 
  18.  
  19. (lldb) p/s string 
  20. (__NSCFConstantString *) $6 = @"QiShare" 
  21.  
  22. (lldb) p/a string 
  23. (__NSCFConstantString *) $7 = 0x000000010416a0b8 @"QiShare" @"QiShare" 

5. 線程

thread是線程相關(guān)的命令,語法為thread [],它可以接受不同的可選參數(shù),以實現(xiàn)豐富的功能。其中thread list、thread backtrace和thread return較為常用。

開發(fā)者可以使用thread list命令查看當(dāng)前的所有線程,示例如下:

  1. (lldb) thread list 
  2. Process 4031 stopped 
  3. * 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 
  4.   thread #2: tid = 0x25d2f, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 
  5.   thread #3: tid = 0x25d30, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 
  6.   thread #4: tid = 0x25d31, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 
  7.   thread #5: tid = 0x25d32, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 
  8.   thread #6: tid = 0x25d33, 0x00000001079ff28a libsystem_kernel.dylib`__workq_kernreturn + 10 
  9.   thread #7: tid = 0x25d3e, 0x00000001079f520a libsystem_kernel.dylib`mach_msg_trap + 10, name = 'com.apple.uikit.eventfetch-thread' 

thread backtrace命令可以方便地供開發(fā)者查看線程堆棧信息,簡寫為bt。比如,當(dāng)程序崩潰的時候,開發(fā)者可以查看堆棧調(diào)用列表。示例如下:

  1. (lldb) thread backtrace 
  2. * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 
  3.     frame #0: 0x0000000104cc2705 libobjc.A.dylib`objc_exception_throw 
  4.     frame #1: 0x00000001056704ec CoreFoundation`_CFThrowFormattedException + 194 
  5.     frame #2: 0x00000001057a6b00 CoreFoundation`-[__NSArrayI objectAtIndexedSubscript:] + 96 
  6.   * frame #3: 0x00000001043a1df7 QiDebugDemo`-[QiConsoleViewController testLLDBCommands](self=0x00007fadc7c50400_cmd="testLLDBCommands") at QiConsoleViewController.m:33 
  7.     frame #4: 0x00000001043a1d5a QiDebugDemo`-[QiConsoleViewController viewDidLoad](self=0x00007fadc7c50400_cmd="viewDidLoad") at QiConsoleViewController.m:26 
  8. ... 
  9.     frame #18: 0x00000001056830be CoreFoundation`__CFRunLoopDoObservers + 430 
  10.     frame #19: 0x0000000105683751 CoreFoundation`__CFRunLoopRun + 1537 
  11.     frame #20: 0x0000000105682e11 CoreFoundation`CFRunLoopRunSpecific + 625 
  12.     frame #21: 0x000000010ddd51dd GraphicsServices`GSEventRunModal + 62 
  13.     frame #22: 0x000000010a1db81d UIKitCore`UIApplicationMain + 140 
  14.     frame #23: 0x00000001043a2450 QiDebugDemo`main(argc=1argv=0x00007ffeeb85df90) at main.m:7 
  15.     frame #24: 0x0000000107858575 libdyld.dylib`start + 1 

在調(diào)試過程中,開發(fā)者可以使用thread return命令終端某個方法并返回一個想要的值。示例如下:

  1. (lldb) thread return string 
  2. (lldb) continue 
  3. 2019-02-27 17:22:47.323225+0800 QiDebugDemo[5071:222700] resultString: Qi_Share 

6. 斷點

作者在iOS 調(diào)試方法:斷點這篇文章中介紹過斷點的用法。其實,可視化的斷點都可以使用LLDB語法來實現(xiàn)。比如下圖中的1、2、3、4、5都能用LLDB命令表達。

  • 啟用/禁用斷點(breakpoint enable/disable)
  • 繼續(xù)執(zhí)行程序(continue)
  • 執(zhí)行下一步(next)
  • 進入方法(step)
  • 跳出方法(finish)

在斷點相關(guān)操作中,因為Xcode已經(jīng)集成了可視化的斷點操作工具,所以breakpoint命令并不被常用。但是,breakpoint命令擁有著十分強大的功能,語法為:breakpoint [],主要命令示例如下:

  1. //! 查看所有斷點 
  2. (lldb) breakpoint list 
  3.  
  4. //! 為所有類中的viewDidAppear:設(shè)置斷點 
  5. (lldb) breakpoint set -n viewDidAppear: 
  6.  
  7. //! 為QiConsoleViewController.m文件中的testLLDBCommands方法設(shè)定斷點 
  8. (lldb) breakpoint set -f QiConsoleViewController.m -n testLLDBCommands 
  9.  
  10. //! 為QiConsoleViewController.m文件中的第32行代碼設(shè)定斷點 
  11. (lldb) breakpoint set -f QiConsoleViewController.m -l 32 
  12.  
  13. //! 為handleString:方法設(shè)定條件斷點,條件為string != nil 
  14. (lldb) breakpoint set - handleString: -c string != nil 

7. 觀察點

想比較于breakpoint是對方法生效的斷點,watchpoint則是對地址生效的斷點。watchpoint類似于KVO的工作原理,當(dāng)觀察到屬性地址里面的東西改變時,就讓程序中斷,其語法為:watchpoint []。其應(yīng)用場景示例如下:

  1. (lldb) watchpoint set variable string 
  2. Watchpoint created: Watchpoint 1: addr = 0x7ffeef497360 size = 8 state = enabled type = w 
  3.     declare @ '/Users/huangxianshuai/Desktop/Products/QiShare/QiDebugDemo/QiDebugDemo/QiConsoleViewController.m:33' 
  4.     watchpoint spec = 'string' 
  5.     new value: 0x00000001007670b8 
  6.  
  7. (lldb) next 
  8.  
  9. Watchpoint 1 hit: 
  10. old value: 0x00000001007670b8 
  11. new value: 0x0000000100767138 
  12.  
  13. (lldb) image lookup -a 0x00000001007670b8 
  14.       Address: QiDebugDemo[0x00000001000040b8] (QiDebugDemo.__DATA.__cfstring + 32) 
  15.       Summary: @"QiShare" 
  16. (lldb) image lookup -a 0x0000000100767138 
  17.       Address: QiDebugDemo[0x0000000100004138] (QiDebugDemo.__DATA.__cfstring + 160) 
  18.       Summary: @"huang" 

image lookup -a 是 image lookup -address 的簡寫,可以查看參數(shù)地址的內(nèi)容。

8. 總結(jié)

文章僅列舉了作者平常使用到的一些LLDB命令,這些命令的確能提高調(diào)試效率。而更多的LLDB命令可以從LLDB Homepage(http://lldb.llvm.org/)或者其他網(wǎng)絡(luò)資源中獲取。

【本文是51CTO專欄機構(gòu)360技術(shù)的原創(chuàng)文章,微信公眾號“360技術(shù)( id: qihoo_tech)”】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2019-04-18 09:31:07

iOS項目開發(fā)斷點代碼

2019-04-12 08:10:33

iOS靜態(tài)分析Xcode

2016-03-01 14:37:38

iOSLLDB調(diào)試技巧

2017-01-19 19:20:35

iOS調(diào)試小技能

2013-05-17 10:54:37

iOS開發(fā)iOS SDK調(diào)試技巧

2017-02-21 12:56:21

iOSMac命令

2018-01-24 15:42:49

命令功能程序

2021-10-14 10:05:17

開源項目代碼

2018-08-09 20:47:41

2021-06-08 09:00:42

Swift 協(xié)議LLDB 命令

2013-07-11 10:16:07

Android調(diào)試

2011-02-21 12:54:47

postfix命令

2013-03-25 11:00:35

互聯(lián)網(wǎng)開發(fā)

2010-02-23 15:32:51

2009-12-30 17:47:54

Ubuntu常用命令

2014-02-10 09:45:36

網(wǎng)絡(luò)故障LinuxPing

2017-03-20 15:58:20

iOS開發(fā)常用宏

2015-12-10 09:43:23

Git命令清單

2023-07-10 07:40:14

2009-06-02 14:15:44

myeclipse jmyeclipse設(shè)置
點贊
收藏

51CTO技術(shù)棧公眾號