BreakPoint & LLDB

前言

記錄一下比較常用的一些 LLDB 調(diào)試技巧.
Note: 在這里是記錄一下常用的方法, 并不是完全教程喲!
Note: 前方多圖(前方高能), 流量慎入. 土豪無視.

BreakPoint


工作中使用斷點對程序進行調(diào)試可以說就跟家常便飯一樣, 我們幾乎天天都會用到. 來看看 Xcode 中如何簡單的使用斷點吧.
在 Xcode 中設(shè)置斷點的方法有如下三種:

  1. 在代碼左側(cè)的行數(shù)那一列中點擊一下, 就會出現(xiàn)一個斷點.
  2. 用鼠標選中你希望下斷點的一行, 然后按 Command + \ 來設(shè)置斷點.
  3. 使用 LLDB 指令生成斷點.

下圖中我們看到的藍色的矩形, 就是表示該行設(shè)置了斷點.

設(shè)置斷點

如果希望一個斷點暫時失效, 點擊藍色矩形區(qū)域, 此時藍色將會變?yōu)榛疑? 表示斷點失效, 如下圖:

使斷點失效

刪除一個斷點也很簡單, 用鼠標拖住矩形區(qū)域, 在代碼區(qū)域放手就可以了, 此時你會看到一個動效并且會聽到的一聲. 如下圖紅色矩形內(nèi)的動效:

刪除一個斷點

對一個斷點進行編輯, 只需要鼠標右鍵點擊斷點, 然后選擇Edit Breakpoint , 如下圖:

編輯斷點

進入斷點編輯模式后, 我們將會看到如下的對話框:

在這里編輯斷點的具體內(nèi)容

在這里我們可以對斷點進行編輯.
Condition: 條件, 這里可以設(shè)置斷點的出發(fā)條件, 例如我們在程序中有一個變量名為 index, 在這里我們設(shè)置條件 index == 1000, 代表只有當(dāng) index 變量為 1000的時候, 斷點才會被觸發(fā).
Ignore: 忽略, 在這里可以設(shè)置斷點被忽略多少次以后觸發(fā).
Action: 我們可以為斷點觸發(fā)的時候添加事件, 譬如: 語音啊, 音效啊, LLDB 指令之類的. 我們會在實戰(zhàn)環(huán)節(jié)使用 Action 來看看效果哈, 不要急.
Options: 把這個對勾勾上的話, 程序不會終止在斷點的位置, 而是會繼續(xù)運行.
來看看下面這個例子:

- (void) addLabel {
    
    UILabel *label = [[UILabel alloc] init];
    label.text = @"Test LLDB";
    [self.view addSubview: label];
}

- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self addRedView];
}

我們寫了一個方法 addLabel, 用來添加一個 label對象, 每次點擊 self.view 都會觸發(fā) addLabel 方法, 可以看到代碼中我們并沒有設(shè)置 label 對象的 frame, 所以無論我們?nèi)绾吸c擊屏幕, label 都是無法顯示出來的, 我們現(xiàn)在為 [self.view addSubview: label] 這句代碼所在的行下一個斷點, 然后編輯這個斷點, 如下圖所示:

對斷點進行編輯后, 是這個樣子的

我來解釋一下這個斷點的意義:

  1. 首先是條件, 只有在 label.text@"Test LLDB"的時候, 斷點才會被觸發(fā).
  2. 其次是忽略次數(shù), 該斷點會被忽略兩次, 也就是你前兩次點擊屏幕的時候, 該斷點是被忽略掉的.
  3. 接下來是事件, 在這個斷點中, 我添加了三個事件, Sound 事件: 觸發(fā)斷點會有一個提示音效. Shell Command 事件: 我這里設(shè)置的是 say, 就是將下面那句話讀出來, %H 代表斷點被Hit 的次數(shù). Debugger Command 事件: 可以添加 LLDB 指令, 在這里我們執(zhí)行了一句代碼, 給 label 對象的 frame 屬性進行了賦值. Log Message 事件: 在這個事件中, 你可以選擇將你輸入的文字打印到控制臺中 或 讀出來. %H 代表斷點被 Hit 的次數(shù), %B 代表函數(shù)名.
  4. 最后自動繼續(xù)運行程序.

除了普通的斷點, Xcode 還提供其他類型的斷點, 例如 Exception Breakpoint, 我們調(diào)試程序的過程中, 我相信很多小伙伴都遇到過那種非常頭疼的 Crash, 就是程序直接Crash 到了 main 函數(shù)中, 這種問題相當(dāng)?shù)牟缓枚ㄎ? 此時可以添加一個 Exception Breakpoint斷點來捕獲異常.

![設(shè)置 Exception Breakpoint]
](http://upload-images.jianshu.io/upload_images/2452150-1e05b780abe42e61.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

在 Xcode 中使用 Command + 7 來查看當(dāng)前程序中的所有斷點. 在這里我們也可以管理斷點, 例如刪除斷點, 關(guān)閉斷點, 編輯斷點等操作. 如下圖:

管理斷點

來看看下面這張圖, 我來依次介紹下圖中按鈕的功能:

控制臺上面的功能按鈕

按鈕從左至右:

  1. 收起控制臺
  2. 開啟/關(guān)閉 所有斷點: 藍色代表開啟, 灰色代表關(guān)閉
  3. 暫停/繼續(xù) 程序: 該按鈕默認行為是暫停應(yīng)用程序, 如果程序當(dāng)前處于暫停狀態(tài), 那么點擊該按鈕為允許程序正常執(zhí)行下去(一直執(zhí)行下去, 或遇到下一個斷點).
  4. 下一步: 會以黑盒的方式執(zhí)行一行代碼。如果所在這行代碼是一個函數(shù)調(diào)用,那么就不會跳進這個函數(shù)尺栖,而是會執(zhí)行這個函數(shù),然后繼續(xù)褥符。
  5. 進入函數(shù)
  6. 退出函數(shù)

這幾個按鈕的作用, 大家在程序中下個斷點自己點點試試就知道了, 很簡單的. 這就是 Xcode 中斷點的最最最基本的應(yīng)用.

LLDB


介紹

語法

po & p

  • po: 打印一個 Objective-C 對象, po 指令實際上是expression -O -- 指令的別名.
  • p: 打印類似 intfloat 等基本數(shù)據(jù)類型和類似 CGRectCGPoint 等結(jié)構(gòu)體. (pprint 的縮寫, 你還可以使用printprin什燕、pri)

看下面這個代碼塊, 在 -(void) viewDidLoad 方法中聲明了幾個變量, 我們用 pop 來打印一下看看效果.

// ViewController.h
@interface ViewController ()
@property (nonatomic, strong) UILabel *titleLabel;
@end


// ViewController.m 
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. 聲明兩個結(jié)構(gòu)體
    CGRect  rect  = CGRectMake(0, 0, 100, 100);
    CGPoint point = CGPointMake(100, 100);
    
    // 2. 聲明兩個基本數(shù)據(jù)類型
    NSInteger index = 100;
    CGFloat width = 200.0f;

    // 3. 聲明兩個 Objective-C 對象
    NSArray *array = [NSArray arrayWithObjects: self.titleLabel, @"LLDBDemo", nil];
    NSDictionary *dictionary = @{
                                 @"kMLObject" : self.titleLabel,
                                 @"kMLTitle" : @"LLDBDemo",
                                 };

    // 4. 創(chuàng)建 titleLabel
    self.titleLabel = [UILabel new];
    self.titleLabel.text = @"LLDBDemo";
    self.titleLabel.font = [UIFont systemFontOfSize: 16];
    self.titleLabel.textColor = [UIColor blackColor];
    [self.view addSubview: self.titleLabel];

    // 在這里打一個斷點
}
    
@end

ok, 代碼片段看完了, Command+R運行程序, 當(dāng)程序運行到斷點終止時, 我們可以再控制臺使用 pop 命令來打印我們剛才聲明的變量. 效果如下:

(lldb) p rect
(CGRect) $0 = (origin = (x = 0, y = 0), size = (width = 100, height = 100))

(lldb) p point
(CGPoint) $1 = (x = 100, y = 100)

(lldb) p index
(NSInteger) $2 = 100

(lldb) p width
(CGFloat) $3 = 200

(lldb) po array
<__NSArrayI 0x610000229580>(
<UILabel: 0x7fb5a2d0b6a0; frame = (0 0; 0 0); text = 'LLDBDemo'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60800008c760>>,
LLDBDemo
)


(lldb) po dictionary
{
    kMLObject = "<UILabel: 0x7fb5a2d0b6a0; frame = (0 0; 0 0); text = 'LLDBDemo'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60800008c760>>";
    kMLTitle = LLDBDemo;
}

(lldb) po self.titleLabel
<UILabel: 0x7fb5a2d0b6a0; frame = (0 0; 0 0); text = 'LLDBDemo'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60800008c760>>

除了以上你看到的這些打印, 你還可以打印更細節(jié)的東西, 以上面代碼塊中的 titleLabelarray 為例:

(lldb) po self.titleLabel.frame
(origin = (x = 0, y = 0), size = (width = 0, height = 0))

(lldb) po self.titleLabel.frame.size.width
0

(lldb) po self.titleLabel.text
LLDBDemo

(lldb) po [array objectAtIndex: 1]
LLDBDemo

可以看到 pop 的功能已經(jīng)很強大了是不?

expression & expr & e

在我們調(diào)試程序的時候, 經(jīng)常會有需要修改一個變量值得場景. 普通的調(diào)試方法, 我們可能會添加一行代碼, 然后重新 Command + R 運行程序, 但這必然會無畏的消耗很多時間. 此時使用 expression 指令就非常的方便. 舉例來說: 我們創(chuàng)建一個 UIView 實例, 添加到 self.view 中, 代碼如下:

    UIView *redView = [[UIView alloc] init];
    redView.frame = CGRectMake(20, 40, 100, 100);
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview: redView];

我們可以在 [self.view addSubview: redView]; 這行代碼的位置下一個斷點, 然后執(zhí)行如下的兩行命令:

e redView.frame = CGRectMake(100, 100, 200, 200)
e redView.backgroundColor = [UIColor blueColor]

然后讓程序繼續(xù)運行起來看看效果, 可以看到原本應(yīng)該為紅色的 view 現(xiàn)在變成了藍色, 并且 view 原本的位置和大小也發(fā)生了改變. 所以expression 指令不僅會改變調(diào)試器中的值, 它實際上是真正的改變了程序中的值, 有了這個東西, 代碼調(diào)試起來可就太爽了. 有些時候你可能不想繼續(xù)運行程序, 但是仍然想看到你修改的效果, 那怎么辦? 此時就應(yīng)該執(zhí)行完你的修改之后, 刷新一下界面, 代碼如下:

e redView.frame = CGRectMake(100, 100, 200, 200)
e redView.backgroundColor = [UIColor blueColor]
e [CATransaction flush]

刷新頁面之后, 你無需繼續(xù)運行程序, 就可以馬上看到效果.

call

call 指令代表著調(diào)用某個方法. 實際上call粘勒、 p竞端、print這三個指令都是 expression 指令的別名, 實際上的運行效果是一樣的, 舉例來說明, 看如下代碼塊:

(lldb) print self.view
(UIView *) $2 = 0x00007f9769509660
(lldb) expression self.view
(UIView *) $3 = 0x00007f9769509660
(lldb) call self.view
(UIView *) $4 = 0x00007f9769509660
(lldb) e self.view
(UIView *) $5 = 0x00007f9769509660
(lldb) p self.view
(UIView *) $6 = 0x00007f9769509660

可以很清楚地看到, 這幾個指令實際上的效果是一樣的.

$符號

上文中簡介p 的時候, 我們看到代碼塊中會有這樣的東西, 例如: (NSInteger) $2 = 100(CGFloat) $3 = 200. 這些以$符號開頭的東東實際就是 LLDB 的命名空間的產(chǎn)物, 我們可以用這些東東來進行調(diào)試, 來看看下面這段:

// ViewController.m 
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    CGRect  rect  = CGRectMake(0, 0, 100, 100);

    // 在這里打一個斷點
}
    
@end

viewDidLoad 中隨便聲明了一個CGRect 變量, 然后在下方打上一個斷點, 我們用如下指令調(diào)試一下:

(lldb) p rect
(CGRect) $3 = (origin = (x = 0, y = 0), size = (width = 100, height = 100))
(lldb) e $3 = CGRectMake(10,10,10,10)
(CGRect) $4 = (origin = (x = 10, y = 10), size = (width = 10, height = 10))
(lldb) p rect
(CGRect) $5 = (origin = (x = 10, y = 10), size = (width = 10, height = 10))
(lldb) 

可以看到, 當(dāng)我們 p rect 的時候, 打印的值是我們最初賦的值, 然后我們給 $3賦了一個CGRectMake(10,10,10,10)之后, 再來 p rect, 可以看到此時的 rect 變量已經(jīng)被我們改變了.

Variable 變量

在某些場景中, 我們調(diào)試代碼的時候可能需要創(chuàng)建新的變量來輔助我們, 此時我們?nèi)匀徊恍枰薷拇a后Command+R 重新跑程序, LLDB 同樣提供了相應(yīng)的方法. 我們可以像正常寫代碼一樣, 創(chuàng)建一個 UIView 的實例, 然后將它添加到 self.view 中, 但是唯一不同的是, 聲明的變量名需要以美元符號$開頭. 看下面這個代碼塊:

(lldb) expression UIView *$view = [[UIView alloc] init]
(lldb) expression $view.backgroundColor = [UIColor blackColor]
(lldb) expression $view.frame = CGRectMake(0, 300, 100, 100);
(lldb) expression [self.view addSubview: $view]

此時我們將程序繼續(xù)運行, self.view 中就會新增了一個黑色的view.

thread backtrace & bt 查看調(diào)用堆棧

bt 指令就是查看調(diào)用堆棧的信息, 調(diào)用堆棧信息在程序運行到斷點時 或 崩潰時, 在 Xcode 左側(cè)導(dǎo)航區(qū)域中會自動顯示出來, 如下圖:

Xcode 調(diào)用堆棧

圖中可以清晰的看到, 程序當(dāng)前正處于 Thread1addRedView方法中 (這玩意不會看的請自行 Google吧寶貝兒) . 除了在 Xcode 左側(cè)導(dǎo)航區(qū)域中我們可以查看調(diào)用堆棧, 我們同樣還可以使用 LLDB 為我們提供的 bt 指令進行查看. bt 指令只會查看當(dāng)前線程的調(diào)用堆棧, 如果你希望查看全部的調(diào)用堆棧, 那么就需要使用 bt all 指令了. (Note: 左側(cè)數(shù)字代表了堆棧塊的編號, 這個一會我們會用到.)

frame 相關(guān)指令

講解 frame 相關(guān)指令之前, 先來看一小段示例代碼:

- (void) viewDidLoad {
    [super viewDidLoad];
    
    // 1. Create Blue View
    UIView *blueView = [[UIView alloc] initWithFrame: CGRectMake(20, 20, 100, 100)];
    [blueView setBackgroundColor: [UIColor blueColor]];
    [self.view addSubview: blueView];
    
    // 2. Add Red View
    [self addRedView];
}

- (void) addRedView {
    
    UIView *redView = [[UIView alloc] initWithFrame: CGRectMake(20, 140, 100, 100)];
    [redView setBackgroundColor: [UIColor redColor]];
    [self.view addSubview: redView]; // 斷點所在行
}

Command+R 運行, 程序?qū)V乖?[self.view addSubview: redView]; 這一行.

frame info & fr info

查看當(dāng)前堆棧信息, 以上文提到示例代碼為例執(zhí)行以下命令:

(lldb) frame info
frame #0: 0x000000010a952676 LLDBDemo`-[ViewController addRedView](self=0x00007f8f28409eb0, _cmd="addRedView") + 230 at ViewController.m:88

可以看到, frame info 指令可以查看當(dāng)前所在堆棧的信息. 其中包括方法名庙睡、文件名事富、行號等信息.

frame select & fr sel

在工作中, 我們可能會有這樣的需求, 在調(diào)試一個相對較復(fù)雜的程序時, 我們可能會打很多斷點, 然后一個斷點一個斷點的追, 但是有時操作失誤錯過了某個斷點, 我們又要重新來過, 這同樣會消耗很多無畏的時間. 以上文的示例代碼為例, 此時程序由于斷點的原因停在了 [self.view addSubview: redView]; 這一行, 并且剛才我們也使用 frame info 指令查看了當(dāng)前的堆棧信息, 我們當(dāng)前處在addRedView方法中, 如果此時我希望修改 viewDidLoad 方法中的 blueView變量怎么辦呢? 我用先 po 一下試試:

(lldb) po blueView
error: use of undeclared identifier 'blueView'

結(jié)果顯然是不行的, 因為當(dāng)前堆棧中, 并沒有 blueView, 也就是說如果我們希望對 blueView 進行任何操作, 我們需要做的第一步, 就是切換到 blueView 對應(yīng)的堆棧當(dāng)中, 那我們?nèi)绾吻袚Q呢? 還記得bt 指令么? 我們先用 bt 指令查看一下調(diào)用堆棧信息, 如下圖:

上面這張圖我只截取了一部分, 可以看到 *代表的就是當(dāng)前堆棧. 還可以看出, viewDidLoad 方法的堆棧編號為 #1. 此時我們使用指令frame select 1 就能切換到 viewDidLoad 方法所在的堆棧塊中:

(lldb) frame select 1
frame #1: 0x0000000108124502 LLDBDemo`-[ViewController viewDidLoad](self=0x00007f8d95905bc0, _cmd="viewDidLoad") + 354 at ViewController.m:81
   78       [self.view addSubview: blueView];
   79       
   80       // 2. Add Red View
-> 81       [self addRedView];
   82   }
   83   
   84   - (void) addRedView {

我們切換到了 blueView 對應(yīng)的堆棧中, 就可以對blueView 變量進行想要的操作了. 例如:

(lldb) po blueView
<UIView: 0x7f8d9350b660; frame = (20 20; 100 100); layer = <CALayer: 0x608000028c80>>

Perfect! 完美!

thread return

thread return 指令有一個可選參數(shù), 該參數(shù)接收一個表達之, 調(diào)用thread return 指令后將會直接跳出當(dāng)前棧幀, 并且返回表達式的值. 這意味這函數(shù)剩余的部分不會被執(zhí)行技俐。這會給 ARC 的引用計數(shù)造成一些問題,或者會使函數(shù)內(nèi)的清理部分失效统台。但是在函數(shù)的開頭執(zhí)行這個命令雕擂,是個非常好的隔離這個函數(shù),偽造返回值的方式 贱勃。(查看中文原文, 英文原文)

假設(shè)我們有一個方法, 是用來判斷傳入的 MLPerson 對象是否是男生的, 但是現(xiàn)在我們希望該方法, 無論何時都返回 YES, 此時我們只需要在該方法的最前面下一個斷點, 然后執(zhí)行 thread return YES 就 OK 了, 如下:

- (BOOL) isBoy:(MLPerson *) person {
    
  // 在這里下一個斷點, 并且執(zhí)行 thread return YES 指令.
    
    return person.gender;
}

breakpoint

本文最開始的部分已經(jīng)介紹過如何使用 Xcode 的 UI 界面來設(shè)置斷點, 在這部分介紹如何使用 LLDB 來下斷點. (breakpoint 這一部分內(nèi)容出自這里).

breakpoint set -n

根據(jù)方法名設(shè)置斷點, 假如我們希望給所有類中的 addLabel 方法下一個斷點:

(lldb) breakpoint set -n addLabel
Breakpoint 2: 4 locations.
breakpoint set -f

針對某一文件中的某一方法設(shè)置斷點, 如果方法沒有寫在文件中(例如父類中, Category 中), 那么設(shè)置該斷點將會失敗.

(lldb) breakpoint set -f ViewController.m -n addLabel 
Breakpoint 3: where = LLDBDemo`-[ViewController addLabel] + 16 at ViewController.m:93, address = 0x000000010b81f480
breakpoint set -l

針對某一文件中的某一行設(shè)置斷點.

(lldb) breakpoint set -f ViewController.m -l 101
Breakpoint 5: where = LLDBDemo`-[ViewController touchesBegan:withEvent:] + 96 at ViewController.m:101, address = 0x000000010b81f5a0
breakpoint set -c

設(shè)置條件斷點(對于條件斷點不明確的小伙伴請在本文中第一部分查看).

(lldb) breakpoint set -f ViewController.m -n isNilString: -c string.length
Breakpoint 9: where = LLDBDemo`-[ViewController isNilString:] + 39 at ViewController.m:107, address = 0x000000010b81f637
breakpoint set -o

設(shè)置一個單次斷點, 該斷點只會觸發(fā)一次:

(lldb) breakpoint set -f ViewController.m -n addLabel -o
Breakpoint 10: where = LLDBDemo`-[ViewController addLabel] + 16 at ViewController.m:93, address = 0x000000010b81f480
breakpoint list

使用該指令查看設(shè)置了哪些斷點, 如下:

(lldb) br li 
Current breakpoints:
19: name = 'addLabel', locations = 1, resolved = 1, hit count = 4
  19.1: where = LLDBDemo`-[ViewController addLabel] + 16 at ViewController.m:93, address = 0x000000010b81f480, resolved, hit count = 4 
breakpoint disable & breakpoint enable

我們可以使用這兩個指令設(shè)置斷點是否開啟(是否可用), 如下:

// 讓斷點 19 暫時失效
(lldb) breakpoint disable 19
1 breakpoints disabled.

// 讓斷點 19 生效
(lldb) breakpoint enable 19
1 breakpoints enabled.
breakpoint delete

該指令代表刪除斷點, 我們可以刪除對應(yīng)編號的斷點, 如下:

(lldb) breakpoint delete 19
1 breakpoints deleted; 0 breakpoint locations disabled.

我們也可以刪除所有的斷點, 刪除所有斷點的時候, 我們會得到一個提示, 讓我們確認是否刪除所有斷點, 此時我們輸入y代表確認刪除, 如下:

(lldb) breakpoint delete
About to delete all breakpoints, do you want to do that?: [Y/n] y
All breakpoints removed. (1 breakpoint)

如果你覺得這個提示太煩了, 你也可以使用 -f 指令來直接刪除所有斷點, 如下:

(lldb) breakpoint delete -f
All breakpoints removed. (1 breakpoint)

breakpoint command

在某些特定的時候, 當(dāng)一個斷點被觸發(fā)了之后, 我們可能需要執(zhí)行一些指令. 比如每次觸發(fā)斷點, 我們都會打印一下堆棧信息, 此時我們可以為斷點需要添加bt 指令, 這樣就可以避免每次觸發(fā)斷點后, 我們再手動輸入指令了.

breakpoint command add

想為一個斷點添加命令, 首先我們必須要創(chuàng)建一個斷點, 如下:

(lldb) breakpoint set -f ViewController.m -n addLabel 
Breakpoint 19: where = LLDBDemo`-[ViewController addLabel] + 16 at ViewController.m:93, address = 0x000000010b81f480

通過設(shè)置斷點, 我們可以看到, 當(dāng)前這個斷點的編號為 19. 那么接下來, 我們就為編號為19的斷點添加指令, 如下:

(lldb) breakpoint command add -o "bt" 19

此時, 編號為 19 的斷點, 就已經(jīng)增加了一條 bt 指令, 當(dāng)每次觸發(fā)該斷點的時候, 都會在控制臺輸出堆棧信息. 在上面代碼塊中的 -o指令的完整寫法是--one-liner, 表示增加一條指令. 如果我們需要給該斷點增加更多的指令, 此時我們就不要使用 -o 命令了, 應(yīng)該像如下這么寫:

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

在這里我們?yōu)榫幪枮?19 的斷點增加了兩條指令分別是 btcontinue, 當(dāng)我們指令輸入完畢, 再輸入 DONE 就代表結(jié)束. Note: 多次對同一個斷點添加指令, 后面的指令則會覆蓋前面的指令.

breakpoint command list

使用該指令, 可以查看某一斷點中附加的指令, 我們嘗試查看一下編號為 19 的斷點中附加的指令, 如下:

(lldb) breakpoint command list 19
Breakpoint 19:
    Breakpoint commands:
      bt
      continue
breakpoint command delete

使用該指令, 可以刪除某一斷點中附加的指令, 我們嘗試刪除一下編號為 19 的斷點中附加的指令, 如下:

(lldb) breakpoint command delete 19
(lldb) breakpoint command list 19
Breakpoint 19 does not have an associated command.

breakpoint這一部分中的命令, 其實完全可以使用 Xcode 為我們提供的 UI 界面來實現(xiàn), 更直觀, 更方便. 所以這部分基本上就是從這篇文章中摘抄過來的. 有興趣的同學(xué)可以看看原文, 寫的還是挺 Nice 的.

流程控制

流程控制這個東西, 實際上上文中也有提到過, 還記得這張圖么:

如果已經(jīng)忘了這幾個按鈕的作用了, 那就翻到本文最初的位置進行查看.
按鈕從左往右依次對應(yīng)的指令為:

  1. process continue & continue & c
  2. thread step-over & next & n
  3. thread step-in & step & s
  4. step-out & finish

常用快捷鍵

Note: 這部分同樣出自這里

功能 命令
暫停/繼續(xù) Command + Ctrl + Y
斷點設(shè)置/刪除 Command + \
斷點失效/生效 Command + Y
控制臺顯示/隱藏 Command + Shift + Y
光標切換到控制臺 Command + Shift + C
清空控制臺內(nèi)容 Command + K

實戰(zhàn)


說了這么多, 終于到了實戰(zhàn)的時候了, 有人說, 為什么一個 LLDB 操作還要實戰(zhàn)呢? 原因在于.... 這里面真的好多坑啊, 沒有想象中的那么簡單.

暫時先寫這么多, 未完待續(xù)


Lemon龍說:

如果您在文章中看到了錯誤 或 誤導(dǎo)大家的地方, 請您幫我指出, 我會盡快更改

如果您有什么疑問或者不懂的地方, 請留言給我, 我會盡快回復(fù)您

如果您覺得本文對您有所幫助, 您的喜歡是對我最大的鼓勵

如果您有好的文章, 可以投稿給我, 讓更多的 iOS Developer 在簡書這個平臺能夠更快速的成長


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末井赌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贵扰,更是在濱河造成了極大的恐慌仇穗,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戚绕,死亡現(xiàn)場離奇詭異纹坐,居然都是意外死亡,警方通過查閱死者的電腦和手機舞丛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門耘子,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人球切,你說我怎么就攤上這事谷誓。” “怎么了吨凑?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵片林,是天一觀的道長。 經(jīng)常有香客問我怀骤,道長费封,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任蒋伦,我火速辦了婚禮弓摘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痕届。我一直安慰自己韧献,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布研叫。 她就那樣靜靜地躺著锤窑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嚷炉。 梳的紋絲不亂的頭發(fā)上渊啰,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音,去河邊找鬼绘证。 笑死隧膏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嚷那。 我是一名探鬼主播胞枕,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼魏宽!你這毒婦竟也來了腐泻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤队询,失蹤者是張志新(化名)和其女友劉穎贫悄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娘摔,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡窄坦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凳寺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸭津。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肠缨,靈堂內(nèi)的尸體忽然破棺而出逆趋,到底是詐尸還是另有隱情,我是刑警寧澤晒奕,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布闻书,位于F島的核電站,受9級特大地震影響脑慧,放射性物質(zhì)發(fā)生泄漏魄眉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一闷袒、第九天 我趴在偏房一處隱蔽的房頂上張望坑律。 院中可真熱鬧,春花似錦囊骤、人聲如沸晃择。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宫屠。三九已至,卻和暖如春滑蚯,著一層夾襖步出監(jiān)牢的瞬間浪蹂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乌逐,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓创葡,卻偏偏與公主長得像浙踢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子灿渴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

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

  • 轉(zhuǎn)載 與調(diào)試器共舞 - LLDB 的華爾茲: https://objccn.io/issue-19-2/ 推薦:i...
    F麥子閱讀 3,332評論 0 10
  • LLDB的Xcode默認的調(diào)試器洛波,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測的調(diào)試功能骚露。平時用Xc...
    CoderSC閱讀 1,358評論 0 2
  • [轉(zhuǎn)]淺談LLDB調(diào)試器文章來源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,498評論 2 6
  • LLDB的Xcode默認的調(diào)試器蹬挤,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測的調(diào)試功能棘幸。平時用Xc...
    小笨狼閱讀 20,465評論 31 187
  • 寶寶很無聊焰扳,因為天很熱,媽媽不再身邊误续,吃不到喜歡的稀飯咸菜吨悍。 姑娘我很無聊,因為我是條老狗蹋嵌,看不到喜歡的書育瓜,下不到...
    紙字吹閱讀 335評論 0 0