Xcode GDB 調試

來源:互聯網
上載者:User

關於GDB


對於大多數Cocoa程式員來說,最常用的debugger莫過於Xcode內建的調試工具了。而實際上,它正是gdb的一個圖形化封裝。相對於gdb,圖形化帶來了很多便利,但同時也缺少了一些重要功能。而且在某些情況下,gdb反而更加方便。因此,學習gdb,瞭解一下幕後的實質,也是有必要的。


gdb可以通過終端運行,也可以在Xcode的控制台調用命令。本文將通過終端講述一些gdb的基本命令和技巧。


首先,我們來看一個例子:


    #import <Foundation/Foundation.h> 


    int main(int argc, char **argv) 

    { 

        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

        NSLog(@"Hello, world!"); 

        [pool release]; 


        return 0; 

    }


我們把檔案命名為test.m,然後編譯:


    gcc -g -framework Foundation test.m


準備工作已經完成。現在我們可以開始調試了。只要把要調試的檔案名稱作為參數,啟動gdb:


    gdb a.out


gdb啟動後會輸出很多法律聲明之類的資訊。無視它們,最後我們看到一個提示:


    (gdb)


成功!現在debugger和剛才編譯好的程式都被裝載了。不過,現在程式還沒有開始運行。因為gdb在程式開始前把它暫停了,好讓我們有機會設定調試參數。這次我們不需要做特別設定,所以馬上開始運行吧:


    (gdb) run 


    Starting program: /Users/mikeash/shell/a.out 

    Reading symbols for shared libraries .++++....................... done 

    2011-06-16 20:28:53.658 a.out[2946:a0f] Hello, world! 


    Program exited normally. 

    (gdb)


糟糕,程式竟然exited normally了(==|||)。這可不行,我們得讓他崩潰才行。所以我們給這個小程式添加一個bug:


    int x = 42; 

    NSLog("Hello, world! x = %@", x);

nice。這樣一來程式就會漂亮地崩潰了:


    (gdb) run 


    Starting program: /Users/mikeash/shell/a.out 

    Reading symbols for shared libraries .++++....................... done 


    Program received signal EXC_BAD_ACCESS, Could not access memory. 

    Reason: 13 at address: 0x0000000000000000 

    0x00007fff84f1011c in objc_msgSend () 

    (gdb)


如果我們是在shell中直接啟動並執行程式,在崩潰後就會回到shell。不過現在我們是通過gdb啟動並執行,所以現在並沒有跳出。gdb暫停了我們的程式,但依然使之駐留在記憶體中,讓我們有機會做調試。


首先,我們想知道具體是哪裡導致了程式崩潰。gdb已經通過剛才的輸出告知了我們: 函數objc_msgSend就是禍之根源。但是這個資訊並不足夠,因為這個objc_msgSend是objc執行階段程式庫中的函數。我們並不知道它是怎麼調用的。我們關注的是我們自己的代碼。

要知道這一點,我們需要得到當前進程的函數調用棧的情況,以此回溯找到我們自己的方法。這時我們需要用到backtrace命令,一般簡寫為bt:


    (gdb) bt 

    #0 0x00007fff84f1011c in objc_msgSend () 

    #1 0x00007fff864ff30b in _CFStringAppendFormatAndArgumentsAux () 

    #2 0x00007fff864ff27d in _CFStringCreateWithFormatAndArgumentsAux () 

    #3 0x00007fff8657e9ef in _CFLogvEx () 

    #4 0x00007fff87beab3e in NSLogv () 

    #5 0x00007fff87beaad6 in NSLog () 

    #6 0x0000000100000ed7 in main () at test.m:10


現在我們可以看到,程式在test.m的第10行,調用NSLog方法時崩潰了。接下來我們想看一下這次調用的詳細資料。這時我們要用到up命令。up命令可以在棧的各層之間跳轉。本例中,我們的代碼main是#6:


    (gdb) up 6 

    #6 0x0000000100000ed7 in main () at test.m:10 

    9       NSLog("Hello, world! x = %@", x);

這回不僅是函數名,連出錯的那行代碼也列印出來了。但是,我們還可以使用list(簡寫為l)命令,列印出更多資訊:

ps: 如果需要回到棧列表。可以使用down命令。


    (gdb) l 

    5   

    6   int main(int argc, char **argv) 

    7   { 

    8       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    9       int x = 42; 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.