什么是GDB和LLDB
我們在開發(fā)iOS程序的時候常常會用到調(diào)試跟蹤,如何正確的使用調(diào)試器來debug十分重要。xcode里有內(nèi)置的Debugger,老版使用的是GDB,xcode自4.3之后默認使用的就是LLDB了。
GDB:
UNIX及UNIX-like下的調(diào)試工具。
LLDB:
LLDB是個開源的內(nèi)置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安裝C++或者Python插件。
所以他們兩個都是調(diào)試用的Debugger,只是LLDB是比較高級的版本,或者在調(diào)試開發(fā)iOS應用時比較好用,不然人家蘋果為什么換成了LLDB了呢!
lldb與gdb命令名的對照表:http://lldb.llvm.org/lldb-gdb.html
LLDB的使用
在程序里你需要的地方設置斷點。當斷點斷住的時候你就能看到我們進入LLDB調(diào)試器了。

這時我們就可以使用一些LLDB命令來進行一些調(diào)試了。
調(diào)試快捷鍵:(Xcode常用快捷鍵)
command+shift+Y 打開調(diào)試窗口
command+Y 調(diào)試運行程序
command+option+P 繼續(xù)
command+shift+O 跳過
command+shift+I 進入
command+shift+T 跳出
help命令
help會列出所有命令列表,用戶加載的插件一般來說列在最后。
執(zhí)行help 可以打印指定command的幫助信息。
比如:help print會打印內(nèi)建命令print的使用幫助。


print命令
print命令的簡化方式有prin pri p,唯獨pr不能用來作為檢查,因為會和process混淆,幸運的是p被lldb實現(xiàn)為特指print。
實際上你會發(fā)現(xiàn),lldb對于命令的簡稱,是頭部匹配方式,只要不混淆,你可以隨意簡稱某個命令。
例如:

最前面的(int)是類型。$是命令結(jié)果的引用名,使用$0可以進行print $0 + 7這樣打印出17。
輸出view 下 subview 的數(shù)量。
由于 subview 的數(shù)量是一個 int 類型的值,所以我們使用命令p:
(lldb)p (int)[[[self view] subviews] count]
直接調(diào)用方法改變背景顏色之類
其實使用p,po,call都可以調(diào)用方法,只是p和po都是用于輸出的有返回值的。call一般只在不需要顯示輸出,或是方法無返回值時使用。
(lldb)p [self.view setBackgroundColor:[UIColor redColor]]
(lldb)p (void)[CATransaction flush]
上述的p一般使用call比較好,因為方法是沒有返回值的。
po命令
命令po跟p很像。p輸出的是基本類型,po輸出的Objective-C對象。調(diào)試器會輸出這個 object 的 description。
例如:

expression命令
expression的簡寫就是e。可以用expression來聲明新的變量,也可以改變已有變量的值。我們看到e聲明的都是$開頭的變量。我們在使用時也需要加上$符號。
例如:
創(chuàng)建新的變量

注意:如果上面這里輸入以下命令,會發(fā)生錯誤。說明lldb無法判定某一步的計算結(jié)果是什么數(shù)據(jù)類型,這時需要強制類型轉(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 命令可用于尋址,有多個組合命令。比較實用的用法是用于尋找棧地址對應的代碼位置。 下面我寫了一段代碼
NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSLog(@"%@",arr[2]);
這段代碼有明顯的錯誤,程序運行這段代碼后會拋出下面的異常:
*** 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)在,我們懷疑出錯的地址是0x0000000100004af8(可以根據(jù)執(zhí)行文件名判斷,或者最小的棧地址)。為了進一步精確定位,我們可以輸入以下的命令:
(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
我們可以看到,出錯的位置是RootViewController.m的第53行。
設置斷點觸發(fā)條件
