LLDB 是 Xcode 中的默認調試器,支持調試 C、Objective-C、C++,用 LLDB 調試代碼的好處不必多說,基本 Xcode 中常見的調試方式 LLDB 都支持,但 LLDB 還可以在運行時寫和運行一些簡單代碼、運行 Python 代碼來擴展調試的方式。
現在讓我們來總結寫 LLDB 都有哪些調試方式吧~
打印
我們最常用的可能就是進行打印操作,在打下斷點,程序暫時停止,在 console 中寫命令打印一些變量的值:
- po oc對象
會調用oc對象的description方法,將這個對象打印出來 - p 基本數據類型
可以使用 print、或其簡寫 p 打印一些基本數據類型
Help
- help 命令
下面講的所有命令都可以通過 help 查看其具體含義、信息
Breakpoint
可以直接用寫命令的方式打斷點、調試、編輯斷點信息:
b 某文件.m:30
給 某文件的第30行打下一個斷點br l
列出當前工程的所有斷點信息br delete n
刪除第n個斷點br enable n
使第n個斷點有效br disable n
使第n個斷點失效br set -n 某方法
設置關于這個方法的符號斷點,在調用這個方式時,程序都會暫停br mod -c "某條件" n
設置條件斷點,給第n個斷點加一個條件
在斷點停下后,還可以像按這些鍵一樣,調試斷點:
- c
Continue,繼續執行 - n
StepOver,一步一步執行方法 - s
StepInto,進入方法調用里面 - finish
StepOut,跳出方法調用
Expression
expr + OC 代碼,在運行時可以執行,對于輸出一些運行時才會確定的變量十分有用。
- expr (void) NSLog(@"balhbalh")
簡單的打印操作 -
expr + 結構體
expr 可以打印結構體的值
打印self.view.bounds -
expr + 變量賦值
這個會實際改變變量的值
運行時改變了 num 的值 - expr + 方法調用
最神奇的莫過于這個,在運行時直接調用指定方法,給運行時加一些“行為”,比如
給斷點添加了一個行為,執行 expr 后面的方法,然后 continue。
這樣每次在ViewController出現時,會執行這個 segue ,推出后面的 Controller,如圖:
Backtrace
- bt
當程序 crash 掉時,可以用 bt 查看程序運行時函數調用的堆棧信息 - bt all
bt 顯示的是當前線程函數調用的信息,可以加 all 顯示所有線程的堆棧信息
Thread
可以操作線程,顯示當前線程信息,在運行時,直接改變方法調用的返回值
- thread list
顯示所有線程信息 - thread select n
選擇第n個線程 - thread backtrace
顯示當前 thread 的堆棧信息 - thread backtrace all
顯示所有 thread 的堆棧信息 - thread until i
使線程運行,并在第 i 行時停下 -
thread return 返回值
直接改變當前方法調用的返回值
isYesOrNo 本來為YES,但是通過 thread return 直接讓其值返回NO
Frame
運行時直接查看變量的值
- frame variable
如上圖,frame variable 直接查看當前變量的值 - frame variable 變量名
查看指定變量名的值
Watchpoint
當變量變化時,程序暫停,顯示 watchpoint 的變化
- watchpoint list
顯示當前所有 watchpoint - watchpoint set variable 變量名
給變量設置 watchpoint - watchpoint modify -c "條件" n
給第n個斷點添加條件,只有滿足條件時,watchpoint 才會觸發 - watchpoint modify -c "" n
條件置空時,即為給這個 watchpoint 刪除條件 - watchpoint set expression -- 內存地址
對任意內存地址進行觀察
Script
lldb 內置了 Python 的腳本解釋器,可以解釋運行 Python 代碼
- breakpoint command add -s python n
給第n個斷點添加python代碼
- breakpoint command add -F "python文件名"."python方法名" n
給第n個斷點添加導入的 python 文件中的方法調用
Command
- command script import "文件路徑/文件名"
導入已有的腳本文件,在調試時可以直接用這個文件 - command import "文件路徑/文件名"
導入已有的 lldb 調試腳本文件 - command unalias pf
刪除用戶自定義的 aliases - command history
打印在當前運行狀態下,lldb 調試時command 歷史
示例:
- 新建一個 empty 文件,文件后綴名為 py,內容為:
def print_locals(frame, bp_loc, internal_dict):
variables = frame.GetVariables(False,True,False,True)
for i in range(0, variables.GetSize()):
variable = variables.GetValueAtIndex(i)
print variable
大概意思為,定義一個方法,會將當前的變量一個一個打印下來
frame 指當前堆棧信息,bp_loc 指斷點的具體位置,internal_dict 這個python 文件的一些參數信息
2.導入 python 代碼
3.給斷點加入 python 代碼中定義的方法
如圖所示:
Alias
當遇到較為復雜的命令,可以給這些命令定義一個別名,每次調用別名即可。
- command alias "別名" 具體命令
給具體命令設置一個別名
上面的方法存在一個問題,設置的別名只在當前運行過程有效,下次就失效了,怎么持久化呢?
可以將這些命令封裝起來,保存在電腦中,每次調試時都可使用。
-
1.新建 lldbinit 文件,在終端中輸入
$ touch ~/.lldbinit
$ open ~/.lldbinit
輸入命令,圖中定義了一個pf命令
2.重啟Xcode,再次編譯運行
3.打斷點,并輸入 pf
Chisel 是 Facebook 開源的一款 lldb 命令集合文件,GitHub 地址。我們可以直接使用一些定義好的 lldb 命令來調試程序。
安裝十分簡單,確保 Mac 已經安裝了 homebrew 環境
$ brew update
$ brew install chisel
安裝成功后會出現
安裝成功
并且提示要將框中出現的命令加在剛剛生成的那個 .lldbint 文件中。
重啟 Xcode 之后,每次就可以使用這些命令了。
在 lldb 中輸入 help,我們發現最下面出現了一些用戶自定義命令,這就是 Chisel 中的。
比較常用的有border,給視圖加邊框;hide,隱藏視圖;mask,給視圖加遮罩;presponder,顯示響應者鏈……
關于 Xcode 調試的文章先總結到這里,希望以后能繼續補充完善??
參考文章
Xcode LLDB Tutorial
The LLDB Debugger
Dancing in the Debugger — A Waltz with LLDB