和 LLDB 調試器來一場說跳就跳的華爾茲(一)

序:原文 Dancing in the Debugger — A Waltz with LLDB
聲明:譯文有一部分參考自:與調試器共舞 - LLDB 的華爾茲


前言

你是否曾經為試圖理解尼的代碼和打印一個變量的值而感到苦惱?

NSLog(@"%@", whatIsInsideThisThing);

或者跳過一個函數調用來簡化程序的行為?

NSNumber *n = @7; // theFunctionThatShouldReallyBeCalled();

或短路一個邏輯檢查?

if (1 || theBooleanAtStake) { ... }

抑或偽造一個函數的實現?

int calculateTheTrickyValue {
  return 9;

  /*
   Figure this out later.
   ...
}

并且每次都必須重新編譯,重新運行嗎?

構建軟件是復雜的,并且bug總是會出現。常見的修復周期是修改代碼,編譯,再次運行,并希望變的最好。

其實并不需要這樣。您可以使用調試器哈!即使你已經知道如何使用調試器來檢查一個變量,可是調試器可以做的遠不止這些。

本文打算挑戰你對調試的認知,更詳細地解釋了一些你可能不知道的基本原理,然后給你展示一些有趣的例子。讓我們隨著舞曲開始旋轉起來,看看我們會以何種水平結束。

LLDB

LLDB 是一個有著 REPL 特性,并內置 C++Python 插件的開源調試器。該調試器捆綁在Xcode內部,并內置于Xcode窗口底部的控制臺面板里。調試器允許您在程序運行的特定時刻暫停程序,來檢查變量的值,執行自定義的指令,然后按照你所認為合適的步驟來操作程序的進展。(這里 是調試器如何工作的大體介紹。)

之前尼很有可能使用過調試器,即使只是在Xcode窗口頁面添加斷點。但是有一些小竅門,可以使你有一些很漂亮而又酷爽的事情去做。GDB to LLDB 參考的是一個偉大的可用命令的鳥瞰圖,你還有可能想要安裝 Chisel ,一個可以使調試器更加有趣的 LLDB 插件的開源合輯。

與此同時,讓我們以 在調試器中如何打印一個變量的值 來開始這場華爾茲的旅程吧。

基礎知識

這里是一段打印一個字符串的簡單示例小程序。注意,在第16行添加了一個斷點:

斷點的示例小程序

程序會在第16行被暫停運行,并且控制臺會被打開,允許我們和調試器交互。那我們應該輸入些什么呢?

help

最簡單的命令是 help ,這一指令將會列出所有的命令。如果你忘記某條命令是做什么的或者想了解更多的命令,你可以使用 help 命令查看更多的細節,例如 help printhelp thread 。如果你忘記了 help 命令是做什么的?你可以使用 help help 命令,但如果你知道的足夠多,也許你還沒有完全忘記命令是做什么的。

print

使用 print 命令打印一個值是很簡單的。

print 的使用

LLDB 實際上會做前綴匹配,因此尼也可以使用 prinprip 命令,但是不可以使用 pr ,因為 LLDB 不能把它和 process 命令做區分(幸運的是,p 并沒有歧義)。
你可能還會注意到,結果中有個 $0。實際上你可以使用它來代指這個結果。試試 print $0 + 7,你會看到 45。任何以美元符開頭的東西都是存在于 LLDB 的命名空間的,它們是為了幫助你進行調試而存在的。

expression

如果想修改一個值怎么辦?這里使用 expression 命令。

expression

這一命令不僅僅修改了調試器中的值,實際上還修改了程序中的值。如果你在這個基礎上繼續執行程序,將會打印83 huang qimeng,神奇吧!
從現在開始,我們下面會使用這兩個命令的簡化形式 pe

什么是 print 命令

這里有一個有趣的表達式:p count = 18,如果我們執行這個命令并打印count的值,我們會看到結果和這個表達式 expression count = 18 是一個吊樣的。

expression不同的是,print不需要參數,比如e -h +17到底是以-h為標識,僅僅執行+17呢,還是計算17h的差值呢?連字符確實讓人困惑,你可能得不到尼想要的結果。

幸運的是解決方式很簡單,使用--表示標識的結束,和輸入的開始,比如以-h作為標識,就要用e -h -- +17,如果想計算它們的差值,就使用e -- -h +17,一般來說,不使用標識的情況比較普遍,所以e --就有了一個簡寫的方式,即print

輸入help print,然后向下滾動,就會發現:

'print' is an abbreviation for 'expression --'.
(print是 `expression --` 的簡寫)

打印對象

輸入:

p objects

然后輸出是一堆奇怪的東西:

(NSString *) $7 = 0x0000000104da4040 @"huang qimeng"

如果我們嘗試打印結構更復雜的對象,結果甚至會更糟:

(lldb) p @[ @"foo", @"bar" ]

(NSArray *) $8 = 0x00007fdb9b71b3e0 @"2 objects"

實際上,我們想看的是對象的 description 方法的結果。我么需要使用 -O (注意是字母 O,而不是數字 0) 標志告訴expression 命令以對象 (Object) 的方式來打印結果。

(lldb) e -O -- $8
<__NSArrayI 0x7fdb9b71b3e0>(
foo,
bar
)

幸運的是,e -o --也有個別名,即poprint object的縮寫),我們可以這樣使用:

(lldb) po $8
<__NSArrayI 0x7fdb9b71b3e0>(
foo,
bar
)
(lldb) po @"lunar"
lunar
(lldb) p @"lunar"
(NSString *) $13 = 0x00007fdb9d0003b0 @"lunar"

打印變量

可以為print指定不同的打印格式。他們都以print/<fmt>或者簡化的p/<fmt>格式書寫。例子如下:
默認格式:

(lldb) p 16
16

十六進制:

(lldb) p/x 16
0x10

二進制(t代表two):

(lldb) p/t 16
0b00000000000000000000000000010000
(lldb) p/t (char)16
0b00010000

你也可以使用p/c打印字符,或者p/s打印以空終止的字符串*char **,這里是輸出格式的完整說明。

變量

現在你已經可以打印對象和簡單類型的變量了,以及如何使用expression命令在調試器中修改他們了。~~此處廢話不翻譯~~,不過為了能使用聲明的變量,變量必須以美元符號$開頭。

(lldb) e int $a = 2
(lldb) p $a * 19
38
(lldb) e NSArray *$array = @[ @"Saturday", @"Sunday", @"Monday" ]
(lldb) p [$array count]
2
(lldb) po [[$array objectAtIndex:0] uppercaseString]
SATURDAY
(lldb) p [[$array objectAtIndex:$a] characterAtIndex:0]
error: no known method '-characterAtIndex:'; cast the message send to the method's return type
error: 1 errors parsing expression

糟了~,LLDB無法分辨涉及的類型(注:返回的類型),這種事情經常出現,給個說明就好了:

(lldb) p (char)[[$array objectAtIndex:$a] characterAtIndex:0]
'M'
(lldb) p/d (char)[[$array objectAtIndex:$a] characterAtIndex:0]
77

變量使調試器的使用變得更容易了,你想不到吧???

未完待續...

移步 和 LLDB 調試器來一場說跳就跳的華爾茲(二)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容