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

摘自大神http://www.starfelix.com/blog/2014/03/17/lldbdiao-shi-ming-ling-chu-tan/

../art/lldb_in_xc5_command_window_2x.png
../art/lldb_in_xc5_command_window_2x.png
如果你在平時(shí)的開(kāi)發(fā)中從未使用過(guò)調(diào)試器肚医,那你恐怕不知道一個(gè)調(diào)試器的作用有多大惜姐。你可能只滿足于通過(guò)printf
或者NSLog
輸出信息用于調(diào)試信不。但你只要試著嘗試在調(diào)試中開(kāi)始使用調(diào)試器LLDB,你會(huì)馬上感受到調(diào)試器給你帶來(lái)的便利堰氓。LLDBLLVM下的調(diào)試器。Xcode從4.0開(kāi)始編譯器開(kāi)始改用LLVM绿淋,相應(yīng)的調(diào)試器也從gdb改為LLDB苗膝。而從 Xcode5.0開(kāi)始所有工程也被自動(dòng)設(shè)置為使用LLDB。下面本文從初學(xué)者的角度講解在日常的開(kāi)發(fā)中如何使用LLDB以及LLDB常用的命令套才。
初識(shí)LLDB
你可能從未使用過(guò)LLDB迂猴,那讓我們先來(lái)熱熱身。 在調(diào)試器中最常用到的命令是p
(用于輸出基本類型)或者po
(用于輸出 Objective-C 對(duì)象)背伴。如下沸毁,你可以通過(guò)輸入po 和 view 來(lái)輸出 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):
[圖片上傳中静檬。勒葱。。(2)]
接下來(lái)運(yùn)行程序巴柿,然后程序會(huì)停留在斷點(diǎn)處凛虽,從下圖你可以看到在什么地方輸入LLDB命令:
[圖片上傳中。广恢。凯旋。(3)]
你可能需要的是 view 下 subview 的數(shù)量。由于 subview 的數(shù)量是一個(gè) int 類型的值,所以我們使用命令p

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

最后你看到的輸出會(huì)是:
(int) $2 = 2

是不是很簡(jiǎn)單至非?細(xì)心的朋友可能會(huì)發(fā)現(xiàn)輸出的信息中帶有$1
钠署、$2
的字樣。實(shí)際上荒椭,我們每次查詢的結(jié)果會(huì)保存在一些持續(xù)變量中($[0-9]+)谐鼎,這樣你可以在后面的查詢中直接使用這些值。比如現(xiàn)在我接下來(lái)要重新取回$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ì)的使用可以參見(jiàn)這個(gè)文章
常用命令
下面補(bǔ)充說(shuō)明其它一些常用的命令:
expr

可以在調(diào)試時(shí)動(dòng)態(tài)執(zhí)行指定表達(dá)式味悄,并將結(jié)果打印出來(lái)草戈。常用于在調(diào)試過(guò)程中修改變量的值。[圖片上傳中侍瑟。唐片。。(4)]如圖設(shè)置斷點(diǎn)涨颜,然后運(yùn)行程序费韭。程序中斷后輸入下面的命令:
expr a=2

你會(huì)看到如下的輸出:
(int) $0 = 2

繼續(xù)運(yùn)行程序,程序輸出的信息是:
實(shí)際值:2

很明顯可以看出庭瑰,變量a的值被改變星持。 除此之外,還可以使用這個(gè)命令新聲明一個(gè)變量對(duì)象见擦,如:
expr int $b=2p $b

下面的命令用于輸出新聲明對(duì)象的值钉汗。(注意,對(duì)象名前要加$)
call

call即是調(diào)用的意思鲤屡。其實(shí)上述的po和p也有調(diào)用的功能损痰。因此一般只在不需要顯示輸出,或是方法無(wú)返回值時(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ì)舉例說(shuō)明,感興趣的朋友可以自己試試就乓。
image

image 命令可用于尋址汉匙,有多個(gè)組合命令拱烁。比較實(shí)用的用法是用于尋找棧地址對(duì)應(yīng)的代碼位置。 下面我寫了一段代碼
NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];NSLog(@"%@",arr[2]);

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

*** 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行屯援。
更多的命令可以參見(jiàn)這個(gè)網(wǎng)址猛们。另外,facebook開(kāi)源了他們擴(kuò)展的LLDB命令庫(kù)玄呛,有興趣的朋友也可以安裝看看阅懦。
簡(jiǎn)稱和別名
很多時(shí)候和二,LLDB完整的命令是很長(zhǎng)的徘铝。比如前面所說(shuō)的image lookup --address
這個(gè)組合命令。為了方便日常的使用惯吕,提高效率惕它,LLDB命令也提供通過(guò)簡(jiǎn)稱的方式調(diào)用命令。還是這個(gè)命令废登,我們用簡(jiǎn)稱就可以寫為im loo -a
淹魄,是不是簡(jiǎn)單多了。如果你是從gdb時(shí)代就開(kāi)始使用調(diào)試器的堡距,你會(huì)發(fā)現(xiàn)甲锡,有些命令如p
、call
等命令和gdb下是一致的羽戒。其實(shí)這些命令是LLDB一些命令的別名缤沦,比如p
是frame variable
的別名,p view
實(shí)際上是frame variable view
易稠。除了系統(tǒng)自建的LLDB別名缸废,你也可以自定義別名。比如下面這個(gè)命令
command alias ioa image lookup --address %1

是將我前面所介紹過(guò)的一個(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ì)展開(kāi)届巩,有興趣的朋友可以查看這個(gè)網(wǎng)址
常見(jiàn)問(wèn)題
上面我們簡(jiǎn)單的學(xué)習(xí)了如何使用LLDB命令份乒。但有時(shí)我們?cè)谑褂眠@些LLDB命令的時(shí)候恕汇,依然可能會(huì)遇到一些問(wèn)題零酪。
不明類型或者類型不匹配
比如下面這個(gè)命令。
(lldb) p NSLog(@"%@",[self.view viewWithTag:1001])error: 'NSLog' has unknown return type; cast the call to its declared return typeerror: 1 errors parsing expression

如果在使用LLDB命令中發(fā)現(xiàn)有 unknown type 的類似錯(cuò)誤(多見(jiàn)于id類型拇勃,比如NSArray中某個(gè)值)四苇,那我們就必須顯式聲明類型。比如上面這個(gè)命令方咆,我們得這么修改月腋。
p (void)NSLog(@"%@",[self.view viewWithTag:1001])

這樣就能得到正確的結(jié)果了。 另外瓣赂,lldb是不支持宏的榆骚,需要我們自己替換。
找不到方法
常見(jiàn)于輸出frame的時(shí)候煌集。比如你可能會(huì)得到以下的錯(cuò)誤信息:
1234

(lldb) po self.view.frameerror: unsupported expression with unknown typeerror: unsupported expression with unknown typeerror: 2 errors parsing expression

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碉钠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子卷拘,更是在濱河造成了極大的恐慌喊废,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栗弟,死亡現(xiàn)場(chǎng)離奇詭異污筷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乍赫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門瓣蛀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人雷厂,你說(shuō)我怎么就攤上這事惋增。” “怎么了罗侯?”我有些...
    開(kāi)封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵器腋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我钩杰,道長(zhǎng)纫塌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任讲弄,我火速辦了婚禮措左,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘避除。我一直安慰自己怎披,他們只是感情好胸嘁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著凉逛,像睡著了一般性宏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上状飞,一...
    開(kāi)封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天毫胜,我揣著相機(jī)與錄音,去河邊找鬼诬辈。 笑死酵使,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焙糟。 我是一名探鬼主播口渔,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼穿撮!你這毒婦竟也來(lái)了缺脉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤混巧,失蹤者是張志新(化名)和其女友劉穎枪向,沒(méi)想到半個(gè)月后勤揩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體咧党,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年陨亡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傍衡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡负蠕,死狀恐怖蛙埂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情遮糖,我是刑警寧澤绣的,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站欲账,受9級(jí)特大地震影響屡江,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赛不,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一惩嘉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧踢故,春花似錦文黎、人聲如沸惹苗。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桩蓉。三九已至,卻和暖如春劳闹,著一層夾襖步出監(jiān)牢的瞬間触机,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工玷或, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留儡首,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓偏友,卻偏偏與公主長(zhǎng)得像蔬胯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子位他,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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

  • LLDB調(diào)試命令初探 初識(shí)LLDB 你可能從未使用過(guò)LLDB氛濒,那讓我們先來(lái)熱熱身。 在調(diào)試器中最常用到的命令是p(...
    守候的流年閱讀 342評(píng)論 0 1
  • 初識(shí)LLDB 你可能從未使用過(guò)LLDB鹅髓,那讓我們先來(lái)熱熱身舞竿。在調(diào)試器中最常用到的命令是p(用于輸出基本類型)或者p...
    felix9閱讀 325評(píng)論 0 2
  • 如果你在平時(shí)的開(kāi)發(fā)中從未使用過(guò)調(diào)試器,那你恐怕不知道一個(gè)調(diào)試器的作用有多大窿冯。你可能只滿足于通過(guò)print或者NSL...
    沖上云霄90閱讀 1,028評(píng)論 0 3
  • 轉(zhuǎn)載 與調(diào)試器共舞 - LLDB 的華爾茲: https://objccn.io/issue-19-2/ 推薦:i...
    F麥子閱讀 3,330評(píng)論 0 10
  • 你是否曾經(jīng)苦惱于理解你的代碼骗奖,而去嘗試打印一個(gè)變量的值? NSLog(@"%@", whatIsInsideThi...
    木易林1閱讀 954評(píng)論 0 4