天天看點

GDB常用調試指令以及多程序多線程調試一:普通指令 二:多程序調試三:多線程調試四:core檔案

   今天把所有的GDB常用的調試指令都過了一遍,尤其是多線程調試。是以先做個總結,以免忘記。以後如果有新的有用的指令會繼續追加。

    本文位址:(LYanger的部落格:http://blog.csdn.net/freeelinux/article/details/53700266)

一:普通指令

1.list指令

  • list  linenum      顯示程式第linenum行周圍的程式
  • list  function      顯示函數名為function的函數的源程式
  • list                      顯示目前行後面的源程式
  • list -                    顯示目前行前面的源程式

2.run(r)

    運作指令。

  • run args         run指令可以直接接指令行參數值,也可以在執行run之前通過 set args + 參數值實作。 

3.break(b)

    打斷點,使用方法:

  • b  linenum                        在某行打斷點
  • b  +offset/-offset               在目前行号的前面或後面offset停住
  • b  filename:linenum         在某檔案的某行打斷點
  • b  filename:function         在某檔案某個函數入口停住
  • b  *address                      在程式的運作位址處停住
  • b                                      沒有參數在下一句停住
  • b where if condition         當某個條件滿足時,在某一行停住(這個很有用,比如b 10 if ret == 5)

    對于break指令,我們要靈活使用。例如打多個斷點。多線程程式中我們可以主函數中線程建立後立即打斷點,執行線程函數入口打斷點等。     關閉斷點:delete(d) breakpoint-id

4.單步指令

    普通用法就不說了。

  • step count         一次性執行count步,如果有函數會進入函數
  • next count         一次執行count,不進入函數
  • finish                 運作程式,直到目前函數完成傳回,并列印函數傳回時的堆棧位址和傳回值以及參數資訊
  • until                   退出循環體(尤其是針對for循環這種,很煩的)

5.continue指令

    當程式被停住之後,可以使用continue(c)指令,恢複程式的運作直到程式結束,或到達下一個斷點。 這裡要注意如果沒有斷點程式是會直接結束的。     

6.print(p)指令

    這個指令比較常用,用來檢視我們想看的内容。比如有關數組可以看全部,也可以看從左到右某一部分:

GDB常用調試指令以及多程式多線程調試一:普通指令 二:多程式調試三:多線程調試四:core檔案

    print指令針對變量檢視的輸出格式有:

  • x 按十六進制格式顯示變量
  • d 按十進制格式顯示變量
  • u 按十六進制格式顯示無符号整型
  • o 按八進制格式顯示變量
  • t 按二進制格式顯示變量t 按二進制格式顯示變量
  • a 按十六進制格式顯示變量
  • c 按字元格式顯示變量
  • f 按浮點數格式顯示變量

7.watch指令

    這個指令比較有用。watch一般用來觀察某個表達式(變量也是一種表達式)的值是否有變化,如果有變化,馬上停住程式。我們有一下幾種方法設定觀察點:

  • watch   expr                 為表達式expr設定一個觀察點,一旦表達式值有變化,馬上停住程式
  • rwatch  expr                  當表達式expr被讀時,停住程式
  • awatch expr                  當表達式的值被讀或被寫時,停住程式。
  • info      watchpoints       列出所有觀察點(info指令通常可以去套)

    舉例如下,示範觀測*i的值,一旦變化停下來:

GDB常用調試指令以及多程式多線程調試一:普通指令 二:多程式調試三:多線程調試四:core檔案

         在循環中我們也可以使用watch,配合ignore,它是除了until指令之外又一個可以讓我們跳出循環的方法,不過watch+ignore更強大,可以任意跳轉到第i次循環。它們的意思就是觀察一個變量,可以了解為斷點,ignore這個斷點多少次,然後用continue就可以直接跳過了。

GDB常用調試指令以及多程式多線程調試一:普通指令 二:多程式調試三:多線程調試四:core檔案

8.examine指令

    使用該指令來檢視記憶體位址中的值。文法是:x/u addr      addr表示一個記憶體位址。“x/”後的n、f、u都是可選的參數,n 是一個正整數,表示顯示記憶體的長度,也就是說從目前位址向後顯示幾個位址的内容;f 表示顯示的格式,如果位址所指的是字元串,那麼格式可以是s,如果位址是指令位址,那麼格式可以是i;u 表示從目前位址往後請求的位元組數,如果不指定的話,GDB預設是4位元組。u參數可以被一些字元代替:b表示單位元組,h表示雙位元組,w表示四位元組,g表示八位元組。當我們指定了位元組長度後,GDB會從指定的記憶體位址開始,讀寫指定位元組,并把其當作一個值取出來。n、f、u這3個參數可以一起使用,例如指令“x/3uh 0x54320”表示從記憶體位址0x54320開始以雙位元組為1個機關(h)、16進制方式(u)顯示3個機關(3)的記憶體。

GDB常用調試指令以及多程式多線程調試一:普通指令 二:多程式調試三:多線程調試四:core檔案

9.jump指令

    jump指令不會改變程式棧的内容,一般隻在同一函數内跳轉。

  • jump linespec     指定下一條語句的運作點,linespec可以是linenum,filename+linenum,+offset這幾種形式
  • jump address      跳到代碼行的位址

10.signal指令

使用signal 信号名(如SIGINT)這種方式把信号發送給程式,如果程式注冊了signal_handler函數,還可以進行相應的處理,幫助調試程式。

11.set指令

  • set args       設定指令行參數
  • set env environmentVarname=value 設定環境變量。如:set env USER=benben

12.call指令

  • call function     強制調用某函數

    強制調用某函數,它會顯示函數傳回值(如果函數傳回值不是void)。print指令也可以完成該功能。

13.disassemble指令

    反彙編指令,檢視執行時源代碼的機器碼。

GDB常用調試指令以及多程式多線程調試一:普通指令 二:多程式調試三:多線程調試四:core檔案

二:多程序調試

1.單獨調試子程序

    我們可以先運作程式,然後再另一終端使用ps -ef | grep "main"(main此處是可執行檔案名)搜尋到子程序pid,然後啟動gdb,在将其附加(attach)到gdb調試器上。

  • attach child-pid        使用該指令後,直接run即可,和調試普通程式就沒差別了
  • dettach                     脫離程序

2.使用調試器選項follow-fork-mode

    我們知道如果不設定任何選項,gdb預設調試父程序。調試器選項用法如下:

  • set follow-fork-mode mode     其中mode的可選值是parent和child,分别表示調試父程序和子程序。
  • info inferiors                            查詢正在調試的程序
  • inferior processnum                切換程序

    預設設定下,在調試多程序程式時GDB隻會調試主程序。但是GDB(>V7.0)支援多程序的分别以及同時調試,換句話說,GDB可以同時調試多個程式。隻需要設定follow-fork-mode(預設值:parent)和detach-on-fork(預設值:on)即可。我們還可以使用catch fork指令,如果fork異常,會停止程式。

        follow-fork-mode  detach-on-fork   說明

        parent                     on               隻調試主程序(GDB預設)

        child                        on               隻調試子程序

        parent                     off               同時調試兩個程序,gdb跟主程序,子程序block在fork位置

        child                        off               同時調試兩個程序,gdb跟子程序,主程序block在fork位置

   設定方法:set follow-fork-mode [parent|child]   set detach-on-fork [on|off]

GDB常用調試指令以及多程式多線程調試一:普通指令 二:多程式調試三:多線程調試四:core檔案

三:多線程調試

    gdb調試一般有兩種模式:all-stop模式和no-stop模式(gdb7.0之前不支援no-stop模式)。     1.all-stop模式         在這種模式下, 當你的程式在gdb由于任何原因而停止,所有的線程都會停止,而不僅僅是目前的線程。一般來說,gdb不能單步所有的線程。因為線程排程是gdb無法控制的。 無論什麼時候當gdb停止你的程式,它都會自動切換到觸發斷點的那個線程 。     2.no-stop模式(網絡程式設計常用)         顧名思義,啟動不關模式。當程式在gdb中停止, 隻有目前的線程會被停止,而其他線程将會繼續運作 。這時候step,next這些指令就隻對目前線程起作用。         如果需要打開no-stop模式,可以向~/.gdbinit添加配置檔案:

#Enable the async interface
set target-async 1
#If using the CLI, pagination breaks non-stop
set pagination off
#Finall, turn it on
set non-stop on
           

        gdb支援的命裡有兩種類型:前台的(同步的)和背景(異步 )的。差別很簡單,同步的在輸出提示符之前會等待程式report一些線程已經終止的資訊,異步則是直接傳回。是以我們需要set target-async 1。set pagination off不要出現 Type <return> to continue 的提示資訊 。最後一步是打開。         下面是常用指令:

  • info threads                                       顯示所有線程
  • thread id                                            切換到指定線程
  • break filename:linenum thread all     在所有線程相應行設定斷點,注意如果主線程不會執行到該行,并且啟動all-stop模式,主線程執行n或s會切換過去
  • set scheduler-locking off|on\step       預設off,執行s或c其它線程也同步執行。on,隻有目前相稱執行。step,隻有目前線程執行
  • show scheduler-locking                     顯示目前模式
  • thread apply all command                 每個線程執行同意指令,如bt。或者thread apply 1 3 bt,即線程1,3執行bt。

        主要是我們要用能用的上的,比如no-stop模式,一般多線程調試就很有用的。

四:core檔案

  • ulimit -c unlimited           生成core檔案,也可以是指定大小,然後使用gdb ./main core啟動,bt檢視調用棧即可。

    參考: https://segmentfault.com/a/1190000003733061                 http://www.cnblogs.com/frankbadpot/archive/2010/06/23/1762916.html

繼續閱讀