iOS開(kāi)發(fā)斷點(diǎn)調(diào)試高級(jí)技巧

關(guān)于LLDB調(diào)試,很多iOS開(kāi)發(fā)者可能就是停留在會(huì)下簡(jiǎn)單的斷點(diǎn),使用最多命令也就是po。無(wú)可厚非,這些簡(jiǎn)單的調(diào)試對(duì)于簡(jiǎn)單的問(wèn)題來(lái)說(shuō)應(yīng)該是游刃有余。但是如果稍微復(fù)雜一些的問(wèn)題,比如我之前遇到過(guò)友盟SDK里面的一個(gè)問(wèn)題。我很想往里面下一個(gè)斷點(diǎn),可是對(duì)于.a的靜態(tài)庫(kù)來(lái)說(shuō),這根本不可能,最終還是我們組大牛使用命令的方式下了斷點(diǎn)解決了這個(gè)問(wèn)題。感覺(jué)這些知識(shí)很有必要,我于是把LLDB的基本調(diào)試命令都學(xué)習(xí)了一下,并在此與大家分享。

雖然博客很長(zhǎng),不過(guò)耐心看完,然后動(dòng)手實(shí)踐,一定會(huì)有很大幫助。

breakpoint

給某個(gè)文件的某一行下斷點(diǎn)。可以使用如下兩種方法,比如我想給Foo.m文件的26行下一個(gè)斷點(diǎn)。可以使用如下的方法。

(lldb) breakpoint set --file Foo.m --line 26

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

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

斷點(diǎn)成功

也可以使用簡(jiǎn)寫(xiě)的形式如下。

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

當(dāng)然我們也可以直接給某個(gè)函數(shù)下斷點(diǎn),可以使用下面兩種方法

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

當(dāng)然我們也可以在一次命令中為下多個(gè)函數(shù)下斷點(diǎn)

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

我們也可以更明確的指定是方法,如果是C的方法,可以使用如下兩種的方法打斷點(diǎn),第二種方法M需要大寫(xiě)

(lldb) breakpoint set --method cplusFoo
(lldb) breakpoint set -M cplusFoo

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

(lldb) breakpoint set --selector foo

(lldb) breakpoint set -S foo

如果是C語(yǔ)言,還是只能使用上面介紹的--name的方式,不能直接指定對(duì)應(yīng)的方法

當(dāng)然,還有一個(gè)必殺器,就是使用正則,匹配你要打斷點(diǎn)的函數(shù)。這個(gè)不限語(yǔ)言

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

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

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

我們同樣可以對(duì)命令進(jìn)行簡(jiǎn)寫(xiě)。下面兩個(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 
......

我們可以對(duì)斷點(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

除了add,還要delete等命令,這些命令不需要死記硬背,可以使用help命令。

(lldb) help break command
  
      add    -- Add LLDB commands to a breakpoint, to be executed whenever the
                breakpoint is hit.  If no breakpoint is specified, adds the
                commands to the last created breakpoint.
      delete -- Delete the set of commands from a breakpoint.
      list   -- List the script or set of commands to be executed when the
                breakpoint is hit.

要查看更詳細(xì)的命令用途,使用help <command> <subcommand>.比如查看add命令用法

(lldb) help break command add
......

Enter your Python command(s). Type 'DONE' to end.
> def breakpoint_output (bp_no):
>     out_string = "Hit breakpoint number " + repr (bp_no)
>     print out_string
>     return True
> breakpoint_output (1)
> DONE

可以看到其實(shí)這里面的命令大部分是Python腳本,不熟悉Python,暫時(shí)還沒(méi)有仔細(xì)研究。

補(bǔ)充一點(diǎn)使用了之后如何刪除斷點(diǎn)呢,命令說(shuō)明如下。

 breakpoint delete [-Df] [<breakpt-id | breakpt-id-list>]

我現(xiàn)在用breakpoint list查我的進(jìn)程

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 = 29, exact_match = 0, locations = 1, resolved = 1, hit count = 1

  2.1: where = BreakPointDemo`::-[ViewController viewDidLoad]() + 105 at ViewController.mm:30, address = 0x00000001025b55c9, resolved, hit count = 1 

4: name = 'foo', locations = 1, resolved = 1, hit count = 0
  4.1: where = BreakPointDemo`-[Foo foo] + 23 at Foo.m:26, address = 0x00000001025b5517, resolved, hit count = 0 

5: regex = 'cFoo', locations = 2, resolved = 2, hit count = 0
  5.1: where = BreakPointDemo`cFoo + 15 at CFoo.c:13, address = 0x00000001025b591f, resolved, hit count = 0 
  5.2: where = libicucore.A.dylib`icu::MeasureUnit::createCubicFoot(UErrorCode&), address = 0x00000001051b808a, resolved, hit count = 0 

若果我要?jiǎng)h除5.1斷點(diǎn)我就使用breakpoint delete 5.1,如果我要?jiǎng)h除5下面的所有斷點(diǎn),使用breakpoint delete 5,這樣5.1和5.2都會(huì)刪除。

刪除所有的斷點(diǎn)使用

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

watchpoint

這個(gè)主要是用于觀(guān)察變量值的具體變化

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

(lldb) watchpoint set variable a

成功添加watchpoint后結(jié)果如下。

Watchpoint created: Watchpoint 1: addr = 0x7fff5913ca3c size = 4 state = enabled type = w
    declare @ '/Users/jianquan/Xcode/BreakPointDemo/BreakPointDemo/ViewController.mm:25'
    watchpoint spec = 'a'
    new value: 10
    

也可以在這里添加.

添加觀(guān)察

然后我們可以設(shè)置在a的值變化為某個(gè)特定值之后觸。

(lldb) watchpoint modify -c '(a=100)'

我們這個(gè)時(shí)候可以看一下具體斷點(diǎn)的參數(shù),使用watchpoint list命令

(lldb) watchpoint list
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 1: addr = 0x7fff4fcb7a3c size = 4 state = enabled type = w
    declare @ '/Users/jianquan/Xcode/BreakPointDemo/BreakPointDemo/ViewController.mm:25'
    watchpoint spec = 'a'
    new value: 10
    condition = '(a=100)'

可以看到我們觀(guān)察的變量的地址,聲明變量的代碼在第幾行,已經(jīng)具體的變量名是a,當(dāng)前的值是10,觸發(fā)的條件是'(a=100)'

然后我們執(zhí)行如下命令,就可以看到斷點(diǎn)到a的值變?yōu)?00的地方

(lldb) c
Process 16596 resuming
2017-02-09 11:12:14.693 BreakPointDemo[16596:6050498] foo is foo
2017-02-09 11:12:14.693 BreakPointDemo[16596:6050498] bar is bar

Watchpoint 1 hit:
old value: 10
new value: 100

可以看到這個(gè)地方a的值已經(jīng)發(fā)生改變。我們可以再使用watchpoint list命令看看具體值的變化

(lldb) watchpoint list
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 1: addr = 0x7fff4fcb7a3c size = 4 state = enabled type = w
    declare @ '/Users/jianquan/Xcode/BreakPointDemo/BreakPointDemo/ViewController.mm:25'
    watchpoint spec = 'a'
    old value: 10
    new value: 100
    condition = '(a=100)'

當(dāng)然,還有一個(gè)特別好用的命令就是bt命令我們可以用它來(lái)追蹤程序運(yùn)行的過(guò)程。

(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是比較簡(jiǎn)略的信息,-f是比較全面的信息,-v是完整的信息。經(jīng)過(guò)我的實(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

這些命令在我目前日常開(kāi)發(fā)中其實(shí)不怎么使用,可能我功力還不足吧。

thread

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

step-in

我們可以使用thread命令來(lái)做一些斷點(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-開(kāi)頭的這幾個(gè)命令,使用起來(lái)很容易。我個(gè)人感覺(jué)比用鼠標(biāo)點(diǎn)擊斷點(diǎn)好用多了~

EXAMINING THREAD STATE

這個(gè)使用的也主要還是thread命令,主要是使用以下幾個(gè)命令。

檢查當(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)前的線(xiàn)程,可以使用如下的命令得到線(xiàn)程的回溯,這個(gè)詞我也不確定怎么表達(dá)好,backtrace,也可以說(shuō)是追蹤。

 lldb) thread backtrace
* 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
  * frame #0: 0x00000001082185fe BreakPointDemo`::-[ViewController viewDidLoad](self=0x00007ff81b60ab20, _cmd="viewDidLoad") + 158 at ViewController.mm:36
    frame #1: 0x00000001093fda3d UIKit`-[UIViewController loadViewIfRequired] + 1258
    frame #2: 0x00000001093fde70 UIKit`-[UIViewController view] + 27
    frame #3: 0x00000001092c74b5 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 71
    frame #4: 0x00000001092c7c06 UIKit`-[UIWindow _setHidden:forced:] + 293
    frame #5: 0x00000001092db519 UIKit`-[UIWindow makeKeyAndVisible] + 42
    frame #6: 0x0000000109253f8d UIKit`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818
    frame #7: 0x000000010925a0ed UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
    frame #8: 0x000000010925726d UIKit`-[UIApplication workspaceDidEndTransaction:] + 188
    frame #9: 0x000000010c3886cb FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    frame #10: 0x000000010c388544 FrontBoardServices`-[FBSSerialQueue _performNext] + 189
    frame #11: 0x000000010c3888cd FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
    frame #12: 0x0000000108ddc761 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    frame #13: 0x0000000108dc198c CoreFoundation`__CFRunLoopDoSources0 + 556
    frame #14: 0x0000000108dc0e76 CoreFoundation`__CFRunLoopRun + 918
    frame #15: 0x0000000108dc0884 CoreFoundation`CFRunLoopRunSpecific + 420
    frame #16: 0x0000000109255aea UIKit`-[UIApplication _run] + 434
    frame #17: 0x000000010925bc68 UIKit`UIApplicationMain + 159
    frame #18: 0x000000010821899f BreakPointDemo`main(argc=1, argv=0x00007fff579e7600) + 111 at main.m:14
    frame #19: 0x000000010bbee68d libdyld.dylib`start + 1

當(dāng)然我們?nèi)绻肟此芯€(xiàn)程的backtrace,可以使用thread backtrace all命令。內(nèi)容太多,我這里就不演示log輸出了。

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

EXAMINING STACK FRAME STATE

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

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

(lldb) frame variable 
(ViewController *) self = 0x00007ff81b60ab20
(SEL) _cmd = "viewDidLoad"
(int) a = 100
(Foo *) foo = 0x000061800000e820
(BreakPointDemoNameSpace::BreakPointClass *) cplusFoo = 0x3ff0000000000000

要打印某個(gè)變量需要在參數(shù)里面指定,這個(gè)命令我們?cè)谇懊嬉彩褂眠^(guò),比如要查看self

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

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

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

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

(lldb) frame variable *self 

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

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

(lldb) frame select 9 

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

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

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

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

我們可以繼續(xù)以之前的命令來(lái)操作

(lldb) expr self = $0
(ViewController *) $2 = 0x00007fefa4705110

當(dāng)然這個(gè)expr用途感覺(jué)不大。

call

其實(shí)這個(gè)命令完全可以使用po進(jìn)行替代,call一般可以用來(lái)調(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è)簡(jiǎn)單的命令,但是我還是感覺(jué)這是一個(gè)比較重要也比較實(shí)用的命令, 命令可用于尋址。比較實(shí)用的用法是用于尋找棧地址對(duì)應(yīng)的代碼位置。 下面我寫(xiě)了一段代碼

  //測(cè)試image命令使用
    NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
    NSLog(@"%@",arr[2]);

可以很明顯的看到數(shù)組越界了,然后我們運(yùn)行程序,可以看到程序報(bào)如下錯(cuò)誤

*** First throw call stack:
(
    0   CoreFoundation                      0x000000011039dd4b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010fd5421e objc_exception_throw + 48
    2   CoreFoundation                      0x00000001102d82bb -[__NSArrayI objectAtIndex:] + 155
    3   BreakPointDemo                      0x000000010f77d444 -[ViewController viewDidLoad] + 340
    4   UIKit                               0x0000000110963a3d -[UIViewController loadViewIfRequired] + 1258
    5   UIKit                               0x0000000110963e70 -[UIViewController view] + 27
    6   UIKit                               0x000000011082d4b5 -[UIWindow addRootViewControllerViewIfPossible] + 71
    7   UIKit                               0x000000011082dc06 -[UIWindow _setHidden:forced:] + 293
    8   UIKit                               0x0000000110841519 -[UIWindow makeKeyAndVisible] + 42
    9   UIKit                               0x00000001107b9f8d -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818
    10  UIKit                               0x00000001107c00ed -[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
    11  UIKit                               0x00000001107bd26d -[UIApplication workspaceDidEndTransaction:] + 188
    12  FrontBoardServices                  0x00000001138ee6cb __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    13  FrontBoardServices                  0x00000001138ee544 -[FBSSerialQueue _performNext] + 189
    14  FrontBoardServices                  0x00000001138ee8cd -[FBSSerialQueue _performNextFromRunLoopSource] + 45
    15  CoreFoundation                      0x0000000110342761 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    16  CoreFoundation                      0x000000011032798c __CFRunLoopDoSources0 + 556
    17  CoreFoundation                      0x0000000110326e76 __CFRunLoopRun + 918
    18  CoreFoundation                      0x0000000110326884 CFRunLoopRunSpecific + 420
    19  UIKit                               0x00000001107bbaea -[UIApplication _run] + 434
    20  UIKit                               0x00000001107c1c68 UIApplicationMain + 159
    21  BreakPointDemo                      0x000000010f77d8ef main + 111
    22  libdyld.dylib                       0x000000011315468d start + 1
)


我們大概可以猜測(cè)程序是崩潰在第三行l(wèi)og,也就是地址為0x0000000104147544的地方,怎么來(lái)呢,瞎猜的,哈哈。其實(shí)原理很簡(jiǎn)單,因?yàn)槲业腄emo名字叫BreakPointDemo。其他的名字很明顯是系統(tǒng)的庫(kù)。雖然log的21行也有BreakPointDemo,但是經(jīng)過(guò)觀(guān)察應(yīng)該是main函數(shù),不在考慮范圍之內(nèi)。

我們使用imagelookup命令,可以很快的定位到具體的代碼行。

(lldb) image lookup --address 0x000000010f77d444
      Address: BreakPointDemo[0x000000010f77d444] (BreakPointDemo.__TEXT.__text + 644)
      Summary: BreakPointDemo`::-[ViewController viewDidLoad]() + 340 at ViewController.mm:46

看看我們的Xcode文件的代碼。確實(shí)是46行

斷點(diǎn)位置

當(dāng)然還有很多的命令我們可以探索,使用image help可以查看,這些命令我暫時(shí)沒(méi)有接觸過(guò),后續(xù)工作或者學(xué)習(xí)中使用到了我會(huì)更新上來(lái)。

為命令設(shè)置別名

比如pframe variable的別名,p view實(shí)際上是frame variable view。除了系統(tǒng)自建的LLDB別名,你也可以自定義別名。比如下面這個(gè)命令。掌握了規(guī)律之后,任何的命令我們都可以自己設(shè)置別名。

(lldb) command alias bfl breakpoint set -f %1 -l %2
(lldb) bfl Foo.m 12

如果想要撤銷(xiāo)別名使用

(lldb) command unalias bfl

當(dāng)然還有一些LLDB的具體命令,我們可以在官網(wǎng)查看: The LLDB Debugger

Demo地址

總結(jié)

這么長(zhǎng)的文章,看到這里真的不容易,不過(guò)我相信你應(yīng)該有所收獲了。另外我的博客長(zhǎng)期歡迎評(píng)論留言,相互探討,不足之處歡迎批準(zhǔn)指正。

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

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

  • [轉(zhuǎn)]淺談LLDB調(diào)試器文章來(lái)源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,543評(píng)論 2 6
  • 前言 今天花了一天的時(shí)間終于把iOS的幾種常見(jiàn)的調(diào)試方法給學(xué)習(xí)了一下,在這里給大家分享一下LLDB的使用,同時(shí)也是...
    Peak_One閱讀 11,061評(píng)論 5 33
  • 與調(diào)試器共舞 - LLDB 的華爾茲 nangege 2014/12/19 你是否曾經(jīng)苦惱于理解你的代碼,而去嘗試...
    McDan閱讀 887評(píng)論 0 0
  • 隨著Xcode 5的發(fā)布,LLDB調(diào)試器已經(jīng)取代了GDB,成為了Xcode工程中默認(rèn)的調(diào)試器。它與LLVM編譯器一...
    隨風(fēng)飄蕩的小逗逼閱讀 1,413評(píng)論 0 0
  • 在簡(jiǎn)書(shū)的第1篇文章,寫(xiě)得不好多多包涵哦 partition的作用是把環(huán)形緩沖區(qū)中的map輸出分區(qū)存儲(chǔ),以便分配給不...
    i衛(wèi)武閱讀 666評(píng)論 0 0