iOS下lldb中斷點(diǎn)調(diào)試

lldb下臭增,相信大家用的較多的是po,或者使用條件斷點(diǎn)竹习。但是面對復(fù)雜的問題時(shí)誊抛,比如.a靜態(tài)庫,就需要其他調(diào)試方法了整陌。

breakpoint

給某個(gè)文件的某一行下斷點(diǎn)拗窃。可以使用如下兩種方法泌辫,比如我想給Person.m文件的10行下一個(gè)斷點(diǎn)并炮。可以使用如下的方法甥郑。

(lldb) breakpoint set --file Person.m --line 10

如果出現(xiàn)如下提示則說明設(shè)置斷點(diǎn)成功

Breakpoint 2: where = BreakPointDemo`-[Person foo] + 23 at Foo.m:10, address = 0x000000010b22e687

也可以使用簡寫的形式如下逃魄。

(lldb) breakpoint set -f Foo.m -l 10

給一個(gè)函數(shù)下斷點(diǎn)

(lldb) breakpoint set --name foo
(lldb) breakpoint set -n foo

一次性給多個(gè)函數(shù)下斷點(diǎn)

(lldb) breakpoint set --name foo --name bar

OC的方法,可以使用以下兩種方式打斷點(diǎn)澜搅,第二種S需要大寫

(lldb) breakpoint set --selector foo

(lldb) breakpoint set -S foo

使用 正則匹配 你要打斷點(diǎn)的函數(shù)伍俘。這個(gè)不限語言

(lldb) breakpoint set -r cFoo
(lldb) breakpoint set -r foo

也可以指定加載的動(dòng)態(tài)庫

(lldb) breakpoint set --shlib foo.dylib --name foo 
(lldb) breakpoint set -s foo.dylib -n foo

我們同樣可以對命令進(jìn)行簡寫。下面兩個(gè)命令的效果是一樣的

(lldb) breakpoint set -n "-[Foo foo]"
(lldb) br s -n "-[Foo foo]"

查看有多少斷點(diǎn)可以使用

(lldb) breakpoint list

打印結(jié)果如下:

Current breakpoints:
1: file = '/Users/jianquan/Xcode/BreakPointDemo/BreakPointDemo/ViewController.m', line = 20, exact_match = 0, locations = 0 (pending)
2: file = '/Users/jianquan/Xcode/BreakPointDemo/BreakPointDemo/ViewController.mm', line = 33, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  2.1: where = BreakPointDemo`::-[ViewController viewDidLoad]() + 186 at ViewController.mm:34, address = 0x0000000105f8362a, resolved, hit count = 0 
......

我們可以對斷點(diǎn)進(jìn)行相關(guān)的操作勉躺,比如在執(zhí)行到2.1斷點(diǎn)的時(shí)候打印追蹤軌跡癌瘾。bt是

(lldb) breakpoint command add 2.1
Enter your debugger command(s).  Type 'DONE' to end.
> bt
> DONE

刪除所有斷點(diǎn)

(lldb) breakpoint delete

watchpoint

觀察變量值的具體變化
比如我需要觀察某個(gè)變量a的值變化,我可以使用如下命令

(lldb) watchpoint set variable a

bt命令用來追蹤程序的運(yùn)行過程

(lldb) bt
* thread #1: tid = 0x5c52c2, 0x000000010ff465fe BreakPointDemo`::-[ViewController viewDidLoad](self=0x00007f932cc07c50, _cmd="viewDidLoad") + 158 at ViewController.mm:36, queue = 'com.apple.main-thread', stop reason = watchpoint 1
  * frame #0: 0x000000010ff465fe BreakPointDemo`::-[ViewController viewDidLoad](self=0x00007f932cc07c50, _cmd="viewDidLoad") + 158 at ViewController.mm:36
    frame #1: 0x000000011112ba3d UIKit`-[UIViewController loadViewIfRequired] + 1258
 ......

我們可以使用frame命令查看變量a的具體值。

(lldb) frame variable a
(int) a = 100

補(bǔ)充一點(diǎn)watchpoint list的東西饵溅。這個(gè)命令包括了三個(gè)可選參數(shù)妨退,我們可以使用help命令查看具體的值

(lldb) help watchpoint list

       -b ( --brief )
            Give a brief description of the watchpoint (no location info).

       -f ( --full )
            Give a full description of the watchpoint and its locations.

       -v ( --verbose )
            Explain everything we know about the watchpoint (for debugging
            debugger bugs).

-b是比較簡略的信息,-f是比較全面的信息,-v是完整的信息咬荷。經(jīng)過我的實(shí)驗(yàn)冠句,如果使用watchpoint list,默認(rèn)的是 watchpoint list -f

process

使用process命令也可以做很多有趣的操作幸乒。具體能做什么懦底,我們也可使用help命令查看

(lldb) process help

      attach    -- Attach to a process.
      connect   -- Connect to a remote debug service.
      continue  -- Continue execution of all threads in the current process.
      detach    -- Detach from the current target process.
      handle    -- Manage LLDB handling of OS signals for the current target
    ......

查看更詳細(xì)的命令使用help <command> <subcommand>。比如

(lldb) help process attach

thread

其實(shí)這個(gè)功能主要就是斷點(diǎn)調(diào)試?yán)锩娴娜缦逻@個(gè)功能罕扎。


step-in.png

我們可以使用thread命令來做一些斷點(diǎn)的操作聚唐,具體有那些命令我們可以使用thread help進(jìn)行查看

(lldb) thread help

      ......

      select         -- Change the currently selected thread.
      step-in        -- Source level single step, stepping into calls. 
                        Defaults to current thread unless specified.
      step-inst      -- Instruction level single step, stepping into calls. 
                        Defaults to current thread unless specified.
      step-inst-over -- Instruction level single step, stepping over calls. 
                        Defaults to current thread unless specified.
      step-out       -- Finish executing the current stack frame and stop after
                        returning.  Defaults to current thread unless
                        specified.
      step-over      -- Source level single step, stepping over calls. 
                        Defaults to current thread unless specified.
      step-scripted  -- Step as instructed by the script class passed in the -C
                        option.
      until          -- Continue until a line number or address is reached by
                        the current or specified thread.  Stops when returning
                        from the current function as a safety measure.

用得比較多的應(yīng)該是 step-開頭的這幾個(gè)命令,使用起來很容易腔召。我個(gè)人感覺比用鼠標(biāo)點(diǎn)擊斷點(diǎn)好用多了~
檢查當(dāng)前進(jìn)程的狀態(tài)杆查,可以使用如下命令

lldb)  thread list
Process 22323 stopped
* thread #1: tid = 0x62d0d7, 0x00000001082185fe BreakPointDemo`::-[ViewController viewDidLoad](self=0x00007ff81b60ab20, _cmd="viewDidLoad") + 158 at ViewController.mm:36, queue = 'com.apple.main-thread', stop reason = step until
......```
*表明的就是當(dāng)前的線程,可以使用如下的命令得到線程的回溯臀蛛,這個(gè)詞我也不確定怎么表達(dá)好根灯,backtrace,也可以說是追蹤掺栅。

(lldb) thread backtrace

  • thread #1: tid = 0x354e72, 0x0000000103ce94bc RunTimeUse`-[ViewController viewDidLoad](self=0x00007ffea04050e0, _cmd="viewDidLoad") + 140 at ViewController.m:24, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    • frame #0: 0x0000000103ce94bc RunTimeUse-[ViewController viewDidLoad](self=0x00007ffea04050e0, _cmd="viewDidLoad") + 140 at ViewController.m:24 frame #1: 0x0000000104e21c99 UIKit-[UIViewController loadViewIfRequired] + 1258
      frame #2: 0x0000000104e220cc UIKit-[UIViewController view] + 27 frame #3: 0x0000000104cebc51 UIKit-[UIWindow addRootViewControllerViewIfPossible] + 71
      frame #4: 0x0000000104cec3a2 UIKit-[UIWindow _setHidden:forced:] + 293 frame #5: 0x0000000104cffcb5 UIKit-[UIWindow makeKeyAndVisible] + 42
      frame #6: 0x0000000104c78c89 UIKit-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818 frame #7: 0x0000000104c7ede9 UIKit-[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
      frame #8: 0x0000000104c7bf69 UIKit-[UIApplication workspaceDidEndTransaction:] + 188 frame #9: 0x0000000107dd4723 FrontBoardServicesFBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK + 24
      frame #10: 0x0000000107dd459c FrontBoardServices-[FBSSerialQueue _performNext] + 189 frame #11: 0x0000000107dd4925 FrontBoardServices-[FBSSerialQueue _performNextFromRunLoopSource] + 45
      frame #12: 0x0000000104802311 CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 frame #13: 0x00000001047e759c CoreFoundation__CFRunLoopDoSources0 + 556
      frame #14: 0x00000001047e6a86 CoreFoundation__CFRunLoopRun + 918 frame #15: 0x00000001047e6494 CoreFoundationCFRunLoopRunSpecific + 420
      frame #16: 0x0000000104c7a7e6 UIKit-[UIApplication _run] + 434 frame #17: 0x0000000104c80964 UIKitUIApplicationMain + 159
      frame #18: 0x0000000103ce9b1f RunTimeUsemain(argc=1, argv=0x00007fff5bf165e8) + 111 at main.m:14 frame #19: 0x000000010763d68d libdyld.dylibstart + 1
      frame #20: 0x000000010763d68d libdyld.dylib`start + 1
當(dāng)然我們?nèi)绻肟此芯€程的backtrace,可以使用thread backtrace all命令纳猪。內(nèi)容太多氧卧,我這里就不演示log輸出了。

如果我們想單獨(dú)查看某個(gè)線程氏堤,我們可以先使用thread select 2跳到某個(gè)具體的線程沙绝,然后再進(jìn)行其他操作,比如thread backtrace

為了方便的觀測架構(gòu)參數(shù)和本地變量鼠锈,我們可以使用 frame variable 命令

如果我什么參數(shù)也不加闪檬,將會把所有的參數(shù)和本地變量到打印出來。

(lldb) frame variable
(ViewController *) self = 0x00007ffea04050e0
(SEL) _cmd = "viewDidLoad"
(Person *) p = 0x0000610000001940

要打印某個(gè)變量需要在參數(shù)里面指定购笆,這個(gè)命令我們在前面也使用過,比如要查看self

(lldb) frame variable self
(ViewController *) self = 0x00007ff81b60ab20

更進(jìn)一步粗悯,我們可以查看一些子元素

(lldb) frame variable self->isa
(Class) self->isa = ViewController

命令雖然不是完整的表達(dá)式解釋器,當(dāng)時(shí)可以識別一些基本的操作 比如 &, *, ->, []同欠,不是重載運(yùn)算符样傍,數(shù)組也可以使用,因?yàn)閿?shù)組本身也是指針铺遂。

(lldb) frame variable *self

(ViewController) *self = {
UIViewController = {
UIResponder = {
NSObject = {
isa = ViewController
}
......
}

和之前thread命令很類似衫哥,我可以使用frame select去選擇另外的一個(gè)frame

(lldb) frame select 9

如果想看更復(fù)雜的數(shù)據(jù),我們可以使用expression命令

(lldb) expression self
(ViewController *) $0 = 0x00007fefa4705110

更復(fù)雜一些襟锐,我們可以用來輸出一個(gè)表達(dá)式

(lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self)
I have a pointer 0x7fefa4705110.
(int) $1 = 33

#call
其實(shí)這個(gè)命令完全可以使用po進(jìn)行替代撤逢,call一般可以用來調(diào)用不需要返回值的調(diào)試命令,比如更改View的背景顏色,以下兩個(gè)命令都可以達(dá)到相似的作用蚊荣,更改當(dāng)前View的背景顏色值初狰。

(lldb) po [self.view setBackgroundColor:[UIColor redColor]]
(lldb) call [self.view setBackgroundColor:[UIColor redColor]]

#image
這個(gè)比較實(shí)用,可用于尋找棧地址對應(yīng)的代碼位置妇押。

//測試image命令使用
NSArray *a = @[@"1"];
NSLog(@"%@",a[1]);

很顯然跷究,數(shù)組越界了,以下顯示崩潰信息

RunTimeUse[46698:3510999] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010934d34b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000108dae21e objc_exception_throw + 48
2 CoreFoundation 0x00000001093a5bdf -[__NSSingleObjectArrayI objectAtIndex:] + 111
3 RunTimeUse 0x00000001087d9480 -[ViewController viewDidLoad] + 320
4 UIKit 0x0000000109911c99 -[UIViewController loadViewIfRequired] + 1258
5 UIKit 0x00000001099120cc -[UIViewController view] + 27
6 UIKit 0x00000001097dbc51 -[UIWindow addRootViewControllerViewIfPossible] + 71
7 UIKit 0x00000001097dc3a2 -[UIWindow _setHidden:forced:] + 293
8 UIKit 0x00000001097efcb5 -[UIWindow makeKeyAndVisible] + 42
9 UIKit 0x0000000109768c89 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818
10 UIKit 0x000000010976ede9 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
11 UIKit 0x000000010976bf69 -[UIApplication workspaceDidEndTransaction:] + 188
12 FrontBoardServices 0x000000010c8c4723 FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK + 24
13 FrontBoardServices 0x000000010c8c459c -[FBSSerialQueue _performNext] + 189
14 FrontBoardServices 0x000000010c8c4925 -[FBSSerialQueue _performNextFromRunLoopSource] + 45
15 CoreFoundation 0x00000001092f2311 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17
16 CoreFoundation 0x00000001092d759c __CFRunLoopDoSources0 + 556
17 CoreFoundation 0x00000001092d6a86 __CFRunLoopRun + 918
18 CoreFoundation 0x00000001092d6494 CFRunLoopRunSpecific + 420
19 UIKit 0x000000010976a7e6 -[UIApplication _run] + 434
20 UIKit 0x0000000109770964 UIApplicationMain + 159
21 RunTimeUse 0x00000001087d9acf main + 111
22 libdyld.dylib 0x000000010c12d68d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

程序奔潰在3敲霍,地址為:0x00000001087d9480俊马,
因?yàn)槲业腄emo名字叫RunTimeUse。其他的名字很明顯是系統(tǒng)的庫肩杈。雖然log的21行也有RunTimeUse,但是經(jīng)過觀察應(yīng)該是main函數(shù)柴我,不在考慮范圍之內(nèi)。
我們使用`image `的 `lookup`命令扩然,可以很快的定位到具體的代碼行艘儒。

(lldb) image lookup --address 0x00000001087d9480
Address: RunTimeUse[0x0000000100001480] (RunTimeUse.__TEXT.__text + 320)
Summary: RunTimeUse`-[ViewController viewDidLoad] + 320 at ViewController.m:28


![image-lookup-address.png](http://upload-images.jianshu.io/upload_images/1654054-7dd117c55d5e5772.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看出,奔潰在ViewController.m中的第28行夫偶。
當(dāng)然還有一些LLDB的具體命令界睁,我們可以在官網(wǎng)查看: [The LLDB Debugger](http://lldb.llvm.org/lldb-gdb.html)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市兵拢,隨后出現(xiàn)的幾起案子翻斟,更是在濱河造成了極大的恐慌,老刑警劉巖说铃,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件访惜,死亡現(xiàn)場離奇詭異,居然都是意外死亡腻扇,警方通過查閱死者的電腦和手機(jī)债热,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幼苛,“玉大人窒篱,你說我怎么就攤上這事〔把兀” “怎么了舌剂?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長暑椰。 經(jīng)常有香客問我霍转,道長,這世上最難降的妖魔是什么一汽? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任避消,我火速辦了婚禮低滩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘岩喷。我一直安慰自己恕沫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布纱意。 她就那樣靜靜地躺著婶溯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪偷霉。 梳的紋絲不亂的頭發(fā)上迄委,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音类少,去河邊找鬼叙身。 笑死,一個(gè)胖子當(dāng)著我的面吹牛硫狞,可吹牛的內(nèi)容都是我干的信轿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼残吩,長吁一口氣:“原來是場噩夢啊……” “哼财忽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泣侮,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤即彪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后旁瘫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡琼蚯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年酬凳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遭庶。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宁仔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出峦睡,到底是詐尸還是另有隱情翎苫,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布榨了,位于F島的核電站煎谍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏龙屉。R本人自食惡果不足惜呐粘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一满俗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧作岖,春花似錦唆垃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沉删,卻和暖如春渐尿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丑念。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工涡戳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脯倚。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓渔彰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親推正。 傳聞我的和親對象是個(gè)殘疾皇子恍涂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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

  • [轉(zhuǎn)]淺談LLDB調(diào)試器文章來源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,498評論 2 6
  • LLDB闡述 LLDB 是一個(gè)有著 REPL 的特性和 C++ ,Python 插件的開源調(diào)試器。LLDB 綁定在...
    HOULI閱讀 4,118評論 0 2
  • 關(guān)于LLDB調(diào)試植榕,很多iOS開發(fā)者可能就是停留在會下簡單的斷點(diǎn)再沧,使用最多命令也就是po。無可厚非尊残,這些簡單的調(diào)試對...
    JoySeeDog閱讀 13,398評論 42 194
  • 2007-2017 十年 從六歲到十六歲 我們之間 沒有多么轟轟烈烈的感情 也沒有什么驚天動(dòng)地的事情 每次在一起都...
    踏雪來的精靈閱讀 420評論 3 2
  • 期盼已久的考試已經(jīng)結(jié)束了炒瘸,我特別想要感受那種把書扔到空中,大家瘋狂舞動(dòng)的快樂寝衫。這段時(shí)間顷扩,把自己勒得太緊了∥恳悖可以說隘截,...
    冠世墨玉yanzi閱讀 197評論 7 2