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

如果你在平時的開發(fā)中從未使用過調(diào)試器帆谍,那你恐怕不知道一個調(diào)試器的作用有多大叫胁。你可能只滿足于通過print或者NSLog輸出信息用于調(diào)試曙蒸。但你只要試著嘗試在調(diào)試中開始使用調(diào)試器LLDB书劝,你會馬上感受到調(diào)試器給你帶來的便利。

LLDB是LLVM下的調(diào)試器福侈。Xcode從4.0開始編譯器開始改用LLVM,相應(yīng)的調(diào)試器也從gdb改為LLDB徐钠。而從 Xcode5.0開始所有工程也被自動設(shè)置為使用LLDB癌刽。下面本文從初學(xué)者的角度講解在日常的開發(fā)中如何使用LLDB以及LLDB常用的命令。

初識LLDB

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

po [self view]

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

(UIView *) $1 = 0x0824c800 ; layer = ; contentOffset: {0, 0}>

什么?在什么地方可以輸入這個命令失息?OK譬淳,首先,我們需要先設(shè)置一個斷點盹兢。如下圖所示邻梆,我在viewDidLoad:中設(shè)置了一個了一個斷點:

接下來運行程序,然后程序會停留在斷點處绎秒,從下圖你可以看到在什么地方輸入LLDB命令:

你可能需要的是 view 下 subview 的數(shù)量浦妄。由于 subview 的數(shù)量是一個 int 類型的值,所以我們使用命令p:

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

最后你看到的輸出會是:

(int) $2 = 2

是不是很簡單见芹?

細(xì)心的朋友可能會發(fā)現(xiàn)輸出的信息中帶有$1剂娄、$2的字樣。實際上玄呛,我們每次查詢的結(jié)果會保存在一些持續(xù)變量中($[0-9]+)阅懦,這樣你可以在后面的查詢中直接使用這些值。比如現(xiàn)在我接下來要重新取回$1的值:

(lldb) po $1

(UIView *) $1 = 0x0824c800 ; layer = ; contentOffset: {0, 0}>

可以看到徘铝,我們依然可以取到之前[self view]的值耳胎。

LLDB命令還可以用在斷點上惯吕,詳細(xì)的使用可以參見這個文章

常用命令

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

expr

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

如圖設(shè)置斷點,然后運行程序诗轻。程序中斷后輸入下面的命令:

expr a=2

你會看到如下的輸出:

(int) $0 = 2

繼續(xù)運行程序钳宪,程序輸出的信息是:

實際值:2

很明顯可以看出,變量a的值被改變扳炬。 除此之外吏颖,還可以使用這個命令新聲明一個變量對象,如:

expr int $b=2

p $b

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

call

call即是調(diào)用的意思。其實上述的po和p也有調(diào)用的功能劝术。因此一般只在不需要顯示輸出缩多,或是方法無返回值時使用call。 和上面的命令一樣养晋,我們依然在viewDidLoad:里面設(shè)置斷點衬吆,然后在程序中斷的時候輸入下面的命令:

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

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

bt

打印調(diào)用堆棧,加all可打印所有thread的堆棧零酪。不詳細(xì)舉例說明冒嫡,感興趣的朋友可以自己試試。

image

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

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 + 1651? libobjc.A.dylib? ? ? ? ? ? ? ? ? ? 0x00000001016b099e objc_exception_throw + 432? CoreFoundation? ? ? ? ? ? ? ? ? ? ? 0x0000000101909e3f -[__NSArrayI objectAtIndex:] + 1753? ControlStyleDemo? ? ? ? ? ? ? ? ? ? 0x0000000100004af8 -[RootViewController viewDidLoad] + 3124? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010035359e -[UIViewController loadViewIfRequired] + 5625? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x0000000100353777 -[UIViewController view] + 296? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010029396b -[UIWindow addRootViewControllerViewIfPossible] + 587? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x0000000100293c70 -[UIWindow _setHidden:forced:] + 2828? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010029cffa -[UIWindow makeKeyAndVisible] + 519? ControlStyleDemo? ? ? ? ? ? ? ? ? ? 0x00000001000045e0 -[AppDelegate application:didFinishLaunchingWithOptions:] + 67210? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x00000001002583d9 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 26411? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x0000000100258be1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 160512? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010025ca0c -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 66013? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010026dd4c -[UIApplication handleEvent:withNewEvent:] + 318914? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010026e216 -[UIApplication sendEvent:] + 7915? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010025e086 _UIApplicationHandleEvent + 57816? GraphicsServices? ? ? ? ? ? ? ? ? ? 0x0000000103aca71a _PurpleEventCallback + 76217? GraphicsServices? ? ? ? ? ? ? ? ? ? 0x0000000103aca1e1 PurpleEventCallback + 3518? CoreFoundation? ? ? ? ? ? ? ? ? ? ? 0x00000001018d3679 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 4119? CoreFoundation? ? ? ? ? ? ? ? ? ? ? 0x00000001018d344e __CFRunLoopDoSource1 + 47820? CoreFoundation? ? ? ? ? ? ? ? ? ? ? 0x00000001018fc903 __CFRunLoopRun + 193921? CoreFoundation? ? ? ? ? ? ? ? ? ? ? 0x00000001018fbd83 CFRunLoopRunSpecific + 46722? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010025c2e1 -[UIApplication _run] + 60923? UIKit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x000000010025de33 UIApplicationMain + 101024? ControlStyleDemo? ? ? ? ? ? ? ? ? ? 0x0000000100006b73 main + 11525? libdyld.dylib? ? ? ? ? ? ? ? ? ? ? 0x0000000101fe95fd start + 126? ???? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x0000000000000001 0x0 + 1)libc++abi.dylib: terminating with uncaught exception of type NSException

現(xiàn)在蟀架,我們懷疑出錯的地址是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

我們可以看到钩述,出錯的位置是RootViewController.m的第53行寨躁。

更多的命令可以參見這個網(wǎng)址

另外牙勘,facebook開源了他們擴展的LLDB命令庫职恳,有興趣的朋友也可以安裝看看所禀。

簡稱和別名

很多時候,LLDB完整的命令是很長的放钦。比如前面所說的image lookup --address這個組合命令色徘。為了方便日常的使用,提高效率操禀,LLDB命令也提供通過簡稱的方式調(diào)用命令褂策。還是這個命令,我們用簡稱就可以寫為im loo -a颓屑,是不是簡單多了斤寂。

如果你是從gdb時代就開始使用調(diào)試器的,你會發(fā)現(xiàn)揪惦,有些命令如p遍搞、call等命令和gdb下是一致的。其實這些命令是LLDB一些命令的別名器腋,比如p是frame variable的別名溪猿,p view實際上是frame variable view。除了系統(tǒng)自建的LLDB別名纫塌,你也可以自定義別名诊县。比如下面這個命令

command alias ioa image lookup --address %1

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

(lldb) ioa 0x0000000100004af8

Address: ControlStyleDemo[0x0000000100004af8] (ControlStyleDemo.__TEXT.__text + 13288)

Summary: ControlStyleDemo`-[RootViewController viewDidLoad] + 312 at RootViewController.m:53

可以看到措左,我們得到了我們想要的結(jié)果翎冲,而命令卻大大縮短。

這里我就不再詳細(xì)展開媳荒,有興趣的朋友可以查看這個網(wǎng)址抗悍。

常見問題

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

不明類型或者類型不匹配

比如下面這個命令。

(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 的類似錯誤(多見于id類型鱼炒,比如NSArray中某個值)衔沼,那我們就必須顯式聲明類型。比如上面這個命令昔瞧,我們得這么修改指蚁。

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

這樣就能得到正確的結(jié)果了。 另外自晰,lldb是不支持宏的凝化,需要我們自己替換。

找不到方法

常見于輸出frame的時候酬荞。比如你可能會得到以下的錯誤信息:

1234

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

這似乎是lldb的一個bug搓劫,無法通過點屬性訪問的方法打印framework里面的對象瞧哟,但是自己在app里面定義的就可以。我們把上面的命令改動一下:

12

(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)系作者
  • 序言:七十年代末秘蛔,一起剝皮案震驚了整個濱河市陨亡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌深员,老刑警劉巖数苫,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辨液,居然都是意外死亡虐急,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門滔迈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來止吁,“玉大人,你說我怎么就攤上這事燎悍【吹耄” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵谈山,是天一觀的道長俄删。 經(jīng)常有香客問我,道長奏路,這世上最難降的妖魔是什么畴椰? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮鸽粉,結(jié)果婚禮上斜脂,老公的妹妹穿的比我還像新娘。我一直安慰自己触机,他們只是感情好帚戳,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著儡首,像睡著了一般片任。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蔬胯,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天对供,我揣著相機與錄音,去河邊找鬼笔宿。 笑死犁钟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泼橘。 我是一名探鬼主播涝动,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼炬灭!你這毒婦竟也來了醋粟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤重归,失蹤者是張志新(化名)和其女友劉穎米愿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鼻吮,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡育苟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了椎木。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片违柏。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖香椎,靈堂內(nèi)的尸體忽然破棺而出漱竖,到底是詐尸還是另有隱情,我是刑警寧澤畜伐,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布馍惹,位于F島的核電站,受9級特大地震影響玛界,放射性物質(zhì)發(fā)生泄漏万矾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一慎框、第九天 我趴在偏房一處隱蔽的房頂上張望勤众。 院中可真熱鬧,春花似錦鲤脏、人聲如沸们颜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窥突。三九已至,卻和暖如春硫嘶,著一層夾襖步出監(jiān)牢的瞬間阻问,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工沦疾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留称近,地道東北人第队。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像刨秆,于是被迫代替她去往敵國和親凳谦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

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

  • 摘自大神http://www.starfelix.com/blog/2014/03/17/lldbdiao-shi...
    skylor閱讀 310評論 0 1
  • LLDB調(diào)試命令初探 初識LLDB 你可能從未使用過LLDB衡未,那讓我們先來熱熱身尸执。 在調(diào)試器中最常用到的命令是p(...
    守候的流年閱讀 343評論 0 1
  • 轉(zhuǎn)載 與調(diào)試器共舞 - LLDB 的華爾茲: https://objccn.io/issue-19-2/ 推薦:i...
    F麥子閱讀 3,334評論 0 10
  • 與調(diào)試器共舞 - LLDB 的華爾茲 nangege 2014/12/19 你是否曾經(jīng)苦惱于理解你的代碼,而去嘗試...
    McDan閱讀 883評論 0 0
  • 你是否曾經(jīng)苦惱于理解你的代碼缓醋,而去嘗試打印一個變量的值如失? NSLog(@"%@", whatIsInsideThi...
    木易林1閱讀 956評論 0 4