深入了解GDB和LLDB

什么是GDB和LLDB

我們?cè)陂_發(fā)iOS程序的時(shí)候常常會(huì)用到調(diào)試跟蹤,如何正確的使用調(diào)試器來debug十分重要。xcode里有內(nèi)置的Debugger,老版使用的是GDB,xcode自4.3之后默認(rèn)使用的就是LLDB了。

GDB:
UNIX及UNIX-like下的調(diào)試工具。

LLDB:
LLDB是個(gè)開源的內(nèi)置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安裝C++或者Python插件。

所以他們兩個(gè)都是調(diào)試用的Debugger,只是LLDB是比較高級(jí)的版本,或者在調(diào)試開發(fā)iOS應(yīng)用時(shí)比較好用,不然人家蘋果為什么換成了LLDB了呢!

lldb與gdb命令名的對(duì)照表:http://lldb.llvm.org/lldb-gdb.html

LLDB的使用

在程序里你需要的地方設(shè)置斷點(diǎn)。當(dāng)斷點(diǎn)斷住的時(shí)候你就能看到我們進(jìn)入LLDB調(diào)試器了。

這時(shí)我們就可以使用一些LLDB命令來進(jìn)行一些調(diào)試了。

調(diào)試快捷鍵:(Xcode常用快捷鍵)

command+shift+Y 打開調(diào)試窗口
command+Y 調(diào)試運(yùn)行程序
command+option+P 繼續(xù)
command+shift+O 跳過
command+shift+I 進(jìn)入
command+shift+T 跳出

help命令

help會(huì)列出所有命令列表,用戶加載的插件一般來說列在最后。
執(zhí)行help 可以打印指定command的幫助信息。
比如:help print會(huì)打印內(nèi)建命令print的使用幫助。

print命令

print命令的簡(jiǎn)化方式有prin pri p,唯獨(dú)pr不能用來作為檢查,因?yàn)闀?huì)和process混淆,幸運(yùn)的是p被lldb實(shí)現(xiàn)為特指print。

實(shí)際上你會(huì)發(fā)現(xiàn),lldb對(duì)于命令的簡(jiǎn)稱,是頭部匹配方式,只要不混淆,你可以隨意簡(jiǎn)稱某個(gè)命令。

例如:

最前面的(int)是類型。$是命令結(jié)果的引用名,使用$0可以進(jìn)行print $0 + 7這樣打印出17。

輸出view 下 subview 的數(shù)量。

由于 subview 的數(shù)量是一個(gè) int 類型的值,所以我們使用命令p:
(lldb)p (int)[[[self view] subviews] count]

直接調(diào)用方法改變背景顏色之類

其實(shí)使用p,po,call都可以調(diào)用方法,只是p和po都是用于輸出的有返回值的。call一般只在不需要顯示輸出,或是方法無返回值時(shí)使用。
(lldb)p [self.view setBackgroundColor:[UIColor redColor]]
(lldb)p (void)[CATransaction flush]
上述的p一般使用call比較好,因?yàn)榉椒ㄊ菦]有返回值的。

po命令

命令po跟p很像。p輸出的是基本類型,po輸出的Objective-C對(duì)象。調(diào)試器會(huì)輸出這個(gè) object 的 description。

例如:

expression命令

expression的簡(jiǎn)寫就是e??梢杂胑xpression來聲明新的變量,也可以改變已有變量的值。我們看到e聲明的都是$開頭的變量。我們?cè)谑褂脮r(shí)也需要加上$符號(hào)。

例如:

創(chuàng)建新的變量


注意:如果上面這里輸入以下命令,會(huì)發(fā)生錯(cuò)誤。說明lldb無法判定某一步的計(jì)算結(jié)果是什么數(shù)據(jù)類型,這時(shí)需要強(qiáng)制類型轉(zhuǎn)換來告訴lldb。

(lldb) p [[$array objectAtIndex:0] characterAtIndex:0]
error: no known method '-characterAtIndex:'; cast the message send to the method's return type
error: 1 errors parsing expression

(lldb) p (char)[[$array objectAtIndex:0] characterAtIndex:0]
'o'

修改已有變量

image命令

image 命令可用于尋址,有多個(gè)組合命令。比較實(shí)用的用法是用于尋找棧地址對(duì)應(yīng)的代碼位置。 下面我寫了一段代碼

NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSLog(@"%@",arr[2]);

這段代碼有明顯的錯(cuò)誤,程序運(yùn)行這段代碼后會(huì)拋出下面的異常:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
*** First throw call stack:
(
 0   CoreFoundation                      0x0000000101951495 __exceptionPreprocess + 165
 1   libobjc.A.dylib                     0x00000001016b099e objc_exception_throw + 43
2   CoreFoundation                      0x0000000101909e3f -[__NSArrayI objectAtIndex:] + 175
3   ControlStyleDemo                    0x0000000100004af8 -[RootViewController viewDidLoad] + 312
4   UIKit                               0x000000010035359e -[UIViewController loadViewIfRequired] + 562
5   UIKit                               0x0000000100353777 -[UIViewController view] + 29
6   UIKit                               0x000000010029396b -[UIWindow addRootViewControllerViewIfPossible] + 58
7   UIKit                               0x0000000100293c70 -[UIWindow _setHidden:forced:] + 282
8   UIKit                               0x000000010029cffa -[UIWindow makeKeyAndVisible] + 51
9   ControlStyleDemo                    0x00000001000045e0 -[AppDelegate application:didFinishLaunchingWithOptions:] + 672
10  UIKit                               0x00000001002583d9 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 264
11  UIKit                               0x0000000100258be1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1605
12  UIKit                               0x000000010025ca0c -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
13  UIKit                               0x000000010026dd4c -[UIApplication handleEvent:withNewEvent:] + 3189
14  UIKit                               0x000000010026e216 -[UIApplication sendEvent:] + 79
15  UIKit                               0x000000010025e086 _UIApplicationHandleEvent + 578
16  GraphicsServices                    0x0000000103aca71a _PurpleEventCallback + 762
17  GraphicsServices                    0x0000000103aca1e1 PurpleEventCallback + 35
18  CoreFoundation                      0x00000001018d3679 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
19  CoreFoundation                      0x00000001018d344e __CFRunLoopDoSource1 + 478
20  CoreFoundation                      0x00000001018fc903 __CFRunLoopRun + 1939
21  CoreFoundation                      0x00000001018fbd83 CFRunLoopRunSpecific + 467
22  UIKit                               0x000000010025c2e1 -[UIApplication _run] + 609
23  UIKit                               0x000000010025de33 UIApplicationMain + 1010
24  ControlStyleDemo                    0x0000000100006b73 main + 115
25  libdyld.dylib                       0x0000000101fe95fd start + 1
26  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

現(xiàn)在,我們懷疑出錯(cuò)的地址是0x0000000100004af8(可以根據(jù)執(zhí)行文件名判斷,或者最小的棧地址)。為了進(jìn)一步精確定位,我們可以輸入以下的命令:

(lldb)image lookup --address 0x0000000100004af8
(lldb)im loo -a 0x0000000100004af8

命令執(zhí)行后返回:

Address: ControlStyleDemo[0x0000000100004af8] (ControlStyleDemo.__TEXT.__text + 13288)
Summary: ControlStyleDemo`-[RootViewController viewDidLoad] + 312 at RootViewController.m:53

我們可以看到,出錯(cuò)的位置是RootViewController.m的第53行。

設(shè)置斷點(diǎn)觸發(fā)條件

參考

LLDB使用篇
LLDB調(diào)試命令初探

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • [轉(zhuǎn)]淺談LLDB調(diào)試器文章來源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,555評(píng)論 2 6
  • 你是否曾經(jīng)苦惱于理解你的代碼,而去嘗試打印一個(gè)變量的值? NSLog(@"%@", whatIsInsideThi...
    paraneaeee閱讀 1,214評(píng)論 0 7
  • 轉(zhuǎn)載 與調(diào)試器共舞 - LLDB 的華爾茲: https://objccn.io/issue-19-2/ 推薦:i...
    F麥子閱讀 3,349評(píng)論 0 10
  • LLDB的Xcode默認(rèn)的調(diào)試器,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測(cè)的調(diào)試功能。平時(shí)用Xc...
    CoderSC閱讀 1,379評(píng)論 0 2
  • 與調(diào)試器共舞 - LLDB 的華爾茲 nangege 2014/12/19 你是否曾經(jīng)苦惱于理解你的代碼,而去嘗試...
    McDan閱讀 887評(píng)論 0 0