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

../art/lldb_in_xc5_command_window_2x.png
../art/lldb_in_xc5_command_window_2x.png

如果你在平時(shí)的開發(fā)中從未使用過調(diào)試器鞠绰,那你恐怕不知道一個(gè)調(diào)試器的作用有多大。你可能只滿足于通過printf或者NSLog輸出信息用于調(diào)試飒焦。但你只要試著嘗試在調(diào)試中開始使用調(diào)試器LLDB蜈膨,你會(huì)馬上感受到調(diào)試器給你帶來的便利。
LLDBLLVM下的調(diào)試器。Xcode從4.0開始編譯器開始改用LLVM翁巍,相應(yīng)的調(diào)試器也從gdb改為LLDB驴一。而從 Xcode5.0開始所有工程也被自動(dòng)設(shè)置為使用LLDB。下面本文從初學(xué)者的角度講解在日常的開發(fā)中如何使用LLDB以及LLDB常用的命令灶壶。

初識LLDB

你可能從未使用過LLDB肝断,那讓我們先來熱熱身。
在調(diào)試器中最常用到的命令是p(用于輸出基本類型)或者po(用于輸出 Objective-C 對象)驰凛。如下孝情,你可以通過輸入po 和 view 來輸出 view 的信息:

po [self view]

隨后調(diào)試器會(huì)輸出這個(gè) object 的 description。在這個(gè)例子中可能是這樣的信息:

(UIView *) $1 = 0x0824c800 <UITableView: 0x824c800; frame = (0 20; 768 1004); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x74c3010>; layer = <CALayer: 0x74c2710>; contentOffset: {0, 0}>

什么洒嗤?在什么地方可以輸入這個(gè)命令?OK魁亦,首先渔隶,我們需要先設(shè)置一個(gè)斷點(diǎn)。如下圖所示洁奈,我在viewDidLoad:中設(shè)置了一個(gè)了一個(gè)斷點(diǎn):

圖二:斷點(diǎn)圖

接下來運(yùn)行程序间唉,然后程序會(huì)停留在斷點(diǎn)處,從下圖你可以看到在什么地方輸入LLDB命令:

圖三:輸入命令位置

你可能需要的是 view 下 subview 的數(shù)量利术。由于 subview 的數(shù)量是一個(gè) int 類型的值呈野,所以我們使用命令p

p (int)[[[self view] subviews] count]

最后你看到的輸出會(huì)是:

(int) $2 = 2

是不是很簡單?
細(xì)心的朋友可能會(huì)發(fā)現(xiàn)輸出的信息中帶有$1印叁、$2的字樣被冒。實(shí)際上,我們每次查詢的結(jié)果會(huì)保存在一些持續(xù)變量中($[0-9]+)轮蜕,這樣你可以在后面的查詢中直接使用這些值昨悼。比如現(xiàn)在我接下來要重新取回$1的值:

(lldb) po $1
(UIView *) $1 = 0x0824c800 <UITableView: 0x824c800; frame = (0 20; 768 1004); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x74c3010>; layer = <CALayer: 0x74c2710>; contentOffset: {0, 0}>

可以看到,我們依然可以取到之前[self view]的值跃洛。

LLDB命令還可以用在斷點(diǎn)上率触,詳細(xì)的使用可以參見這個(gè)文章

常用命令

下面補(bǔ)充說明其它一些常用的命令:

  • expr

可以在調(diào)試時(shí)動(dòng)態(tài)執(zhí)行指定表達(dá)式,并將結(jié)果打印出來汇竭。常用于在調(diào)試過程中修改變量的值葱蝗。

圖四:expr截圖
圖四:expr截圖

如圖設(shè)置斷點(diǎn),然后運(yùn)行程序细燎。程序中斷后輸入下面的命令:

expr a=2

你會(huì)看到如下的輸出:

(int) $0 = 2

繼續(xù)運(yùn)行程序两曼,程序輸出的信息是:

實(shí)際值:2

很明顯可以看出,變量a的值被改變玻驻。
除此之外合愈,還可以使用這個(gè)命令新聲明一個(gè)變量對象,如:

expr int $b=2
p $b

下面的命令用于輸出新聲明對象的值。(注意佛析,對象名前要加$)

  • call

call即是調(diào)用的意思益老。其實(shí)上述的po和p也有調(diào)用的功能。因此一般只在不需要顯示輸出寸莫,或是方法無返回值時(shí)使用call捺萌。
和上面的命令一樣,我們依然在viewDidLoad:里面設(shè)置斷點(diǎn)膘茎,然后在程序中斷的時(shí)候輸入下面的命令:

call [self.view setBackgroundColor:[UIColor redColor]]

繼續(xù)運(yùn)行程序桃纯,看看view的背景顏色是不是變成紅色的了!在調(diào)試的時(shí)候靈活運(yùn)用call命令可以起到事半功倍的作用披坏。

  • bt

打印調(diào)用堆棧态坦,加all可打印所有thread的堆棧。不詳細(xì)舉例說明棒拂,感興趣的朋友可以自己試試伞梯。

  • image

image 命令可用于尋址,有多個(gè)組合命令帚屉。比較實(shí)用的用法是用于尋找棧地址對應(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)一步精確定位牢屋,我們可以輸入以下的命令:

image lookup --address 0x0000000100004af8

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

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

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


更多的命令可以參見這個(gè)網(wǎng)址烙无。
另外辣之,facebook開源了他們擴(kuò)展的LLDB命令庫,有興趣的朋友也可以安裝看看皱炉。

簡稱和別名

很多時(shí)候怀估,LLDB完整的命令是很長的。比如前面所說的image lookup --address這個(gè)組合命令合搅。為了方便日常的使用多搀,提高效率,LLDB命令也提供通過簡稱的方式調(diào)用命令灾部。還是這個(gè)命令康铭,我們用簡稱就可以寫為im loo -a,是不是簡單多了赌髓。
如果你是從gdb時(shí)代就開始使用調(diào)試器的从藤,你會(huì)發(fā)現(xiàn)催跪,有些命令如pcall等命令和gdb下是一致的夷野。其實(shí)這些命令是LLDB一些命令的別名懊蒸,比如pframe variable的別名,p view實(shí)際上是frame variable view悯搔。除了系統(tǒng)自建的LLDB別名骑丸,你也可以自定義別名。比如下面這個(gè)命令

command alias ioa image lookup --address %1

是將我前面所介紹過的一個(gè)命令image lookup --address添加了一個(gè)ioa的別名妒貌。然后執(zhí)行下面的命令:

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

可以看到通危,我們得到了我們想要的結(jié)果,而命令卻大大縮短灌曙。
這里我就不再詳細(xì)展開菊碟,有興趣的朋友可以查看這個(gè)網(wǎng)址

常見問題

上面我們簡單的學(xué)習(xí)了如何使用LLDB命令在刺。但有時(shí)我們在使用這些LLDB命令的時(shí)候逆害,依然可能會(huì)遇到一些問題。

不明類型或者類型不匹配

比如下面這個(gè)命令增炭。

(lldb) p NSLog(@"%@",[self.view  viewWithTag:1001])
error: 'NSLog' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression

如果在使用LLDB命令中發(fā)現(xiàn)有 unknown type 的類似錯(cuò)誤(多見于id類型,比如NSArray中某個(gè)值)拧晕,那我們就必須顯式聲明類型隙姿。比如上面這個(gè)命令,我們得這么修改厂捞。

p (void)NSLog(@"%@",[self.view  viewWithTag:1001])

這樣就能得到正確的結(jié)果了输玷。
另外,lldb是不支持宏的靡馁,需要我們自己替換欲鹏。

找不到方法

常見于輸出frame的時(shí)候。比如你可能會(huì)得到以下的錯(cuò)誤信息:

(lldb) po self.view.frame
error: unsupported expression with unknown type
error: unsupported expression with unknown type
error: 2 errors parsing expression

這似乎是lldb的一個(gè)bug臭墨,無法通過點(diǎn)屬性訪問的方法打印framework里面的對象赔嚎,但是自己在app里面定義的就可以。我們把上面的命令改動(dòng)一下:

(lldb) p (CGRect)[self.view frame]
(CGRect) $0 = origin=(x=0, y=0) size=(width=320, height=480)

總結(jié)

通過上面一些簡單的講解胧弛,相信朋友們已經(jīng)知道如何使用LLDB命令來提高自己的效率了尤误。Enjoy it!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末结缚,一起剝皮案震驚了整個(gè)濱河市损晤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌红竭,老刑警劉巖尤勋,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喘落,死亡現(xiàn)場離奇詭異,居然都是意外死亡最冰,警方通過查閱死者的電腦和手機(jī)瘦棋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锌奴,“玉大人兽狭,你說我怎么就攤上這事÷故瘢” “怎么了箕慧?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茴恰。 經(jīng)常有香客問我颠焦,道長,這世上最難降的妖魔是什么往枣? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任伐庭,我火速辦了婚禮,結(jié)果婚禮上分冈,老公的妹妹穿的比我還像新娘圾另。我一直安慰自己,他們只是感情好雕沉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布集乔。 她就那樣靜靜地躺著,像睡著了一般坡椒。 火紅的嫁衣襯著肌膚如雪扰路。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼碘勉。 笑死祷杈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼识椰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起深碱,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤腹鹉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后敷硅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體功咒,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愉阎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了力奋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榜旦。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖景殷,靈堂內(nèi)的尸體忽然破棺而出溅呢,到底是詐尸還是另有隱情,我是刑警寧澤猿挚,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布咐旧,位于F島的核電站,受9級特大地震影響绩蜻,放射性物質(zhì)發(fā)生泄漏铣墨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一办绝、第九天 我趴在偏房一處隱蔽的房頂上張望伊约。 院中可真熱鬧,春花似錦孕蝉、人聲如沸屡律。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽超埋。三九已至,卻和暖如春骤肛,著一層夾襖步出監(jiān)牢的瞬間纳本,已是汗流浹背窍蓝。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工腋颠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吓笙。 一個(gè)月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓淑玫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親面睛。 傳聞我的和親對象是個(gè)殘疾皇子絮蒿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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