天天看點

用GDB調試程式(二)

GDB的指令概貌

———————

啟動gdb後,就你被帶入gdb的調試環境中,就可以使用gdb的指令開始調試程式了,gdb的指令可以使用help指令來檢視,如下所示:

    /home/hchen> gdb

    GNU gdb 5.1.1

    Copyright 2002 Free Software Foundation, Inc.

    GDB is free software, covered by the GNU General Public License, and you are

    welcome to change it and/or distribute copies of it under certain conditions.

    Type "show copying" to see the conditions.

    There is absolutely no warranty for GDB.  Type "show warranty" for details.

    This GDB was configured as "i386-suse-linux".

    (gdb) help

    List of classes of commands:

    aliases -- Aliases of other commands

    breakpoints -- Making program stop at certain points

    data -- Examining data

    files -- Specifying and examining files

    internals -- Maintenance commands

    obscure -- Obscure features

    running -- Running the program

    stack -- Examining the stack

    status -- Status inquiries

    support -- Support facilities

    tracepoints -- Tracing of program execution without stopping the program

    user-defined -- User-defined commands

    Type "help" followed by a class name for a list of commands in that class.

    Type "help" followed by command name for full documentation.

    Command name abbreviations are allowed if unambiguous.

    (gdb)

gdb的指令很多,gdb把之分成許多個種類。help指令隻是例出gdb的指令種類,如果要看種類中的指令,可以使用help <class> 指令,如:help breakpoints,檢視設定斷點的所有指令。也可以直接help <command>來檢視指令的幫助。

gdb中,輸入指令時,可以不用打全指令,隻用打指令的前幾個字元就可以了,當然,指令的前幾個字元應該要标志着一個唯一的指令,在Linux下,你可以敲擊兩次TAB鍵來補齊指令的全稱,如果有重複的,那麼gdb會把其例出來。

    示例一:在進入函數func時,設定一個斷點。可以敲入break func,或是直接就是b func

    (gdb) b func

    Breakpoint 1 at 0x8048458: file hello.c, line 10.

    示例二:敲入b按兩次TAB鍵,你會看到所有b打頭的指令:

    (gdb) b

    backtrace  break      bt

    示例三:隻記得函數的字首,可以這樣:

    (gdb) b make_ <按TAB鍵>

    (再按下一次TAB鍵,你會看到:)

    make_a_section_from_file     make_environ

    make_abs_section             make_function_type

    make_blockvector             make_pointer_type

    make_cleanup                 make_reference_type

    make_command                 make_symbol_completion_list

    (gdb) b make_

    GDB把所有make開頭的函數全部例出來給你檢視。

    示例四:調試C++的程式時,有可以函數名一樣。如:

    (gdb) b 'bubble( M-?

    bubble(double,double)    bubble(int,int)

    (gdb) b 'bubble(

    你可以檢視到C++中的所有的重載函數及參數。(注:M-?和“按兩次TAB鍵”是一個意思)

要退出gdb時,隻用發quit或指令簡稱q就行了。

GDB中運作UNIX的shell程式

————————————

在gdb環境中,你可以執行UNIX的shell的指令,使用gdb的shell指令來完成:

    shell <command string>

    調用UNIX的shell來執行<command string>,環境變量SHELL中定義的UNIX的shell将會被用來執行<command string>,如果SHELL沒有定義,那就使用UNIX的标準shell:/bin/sh。(在Windows中使用Command.com或cmd.exe)

還有一個gdb指令是make:

    make <make-args>

    可以在gdb中執行make指令來重新build自己的程式。這個指令等價于“shell make <make-args>”。

在GDB中運作程式

————————

當以gdb <program>方式啟動gdb後,gdb會在PATH路徑和目前目錄中搜尋<program>的源檔案。如要确認gdb是否讀到源檔案,可使用l或list指令,看看gdb是否能列出源代碼。

在gdb中,運作程式使用r或是run指令。程式的運作,你有可能需要設定下面四方面的事。

1、程式運作參數。

    set args 可指定運作時參數。(如:set args 10 20 30 40 50)

    show args 指令可以檢視設定好的運作參數。

2、運作環境。

    path <dir> 可設定程式的運作路徑。

    show paths 檢視程式的運作路徑。

    set environment varname [=value] 設定環境變量。如:set env USER=hchen

    show environment [varname] 檢視環境變量。

3、工作目錄。

    cd <dir> 相當于shell的cd指令。

    pwd 顯示目前的所在目錄。

4、程式的輸入輸出。

    info terminal 顯示你程式用到的終端的模式。

    使用重定向控制程式輸出。如:run > outfile

    tty指令可以指寫輸入輸出的終端裝置。如:tty /dev/ttyb

調試已運作的程式

兩種方法:

1、在UNIX下用ps檢視正在運作的程式的PID(程序ID),然後用gdb <program> PID格式挂接正在運作的程式。

2、先用gdb <program>關聯上源代碼,并進行gdb,在gdb中用attach指令來挂接程序的PID。并用detach來取消挂接的程序。

暫停 / 恢複程式運作

—————————

調試程式中,暫停程式運作是必須的,GDB可以友善地暫停程式的運作。你可以設定程式的在哪行停住,在什麼條件下停住,在收到什麼信号時停往等等。以便于你檢視運作時的變量,以及運作時的流程。

當程序被gdb停住時,你可以使用info program 來檢視程式的是否在運作,程序号,被暫停的原因。

在gdb中,我們可以有以下幾種暫停方式:斷點(BreakPoint)、觀察點(WatchPoint)、捕捉點(CatchPoint)、信号(Signals)、線程停止(Thread Stops)。如果要恢複程式運作,可以使用c或是continue指令。

一、設定斷點(BreakPoint)

    我們用break指令來設定斷點。正面有幾點設定斷點的方法:

    break <function>

        在進入指定函數時停住。C++中可以使用class::function或function(type,type)格式來指定函數名。

    break <linenum>

        在指定行号停住。

    break +offset

    break -offset

        在目前行号的前面或後面的offset行停住。offiset為自然數。

    break filename:linenum

        在源檔案filename的linenum行處停住。

    break filename:function

        在源檔案filename的function函數的入口處停住。

    break *address

        在程式運作的記憶體位址處停住。

    break

        break指令沒有參數時,表示在下一條指令處停住。

    break ... if <condition>

        ...可以是上述的參數,condition表示條件,在條件成立時停住。比如在循環境體中,可以設定break if i=100,表示當i為100時停住程式。

    檢視斷點時,可使用info指令,如下所示:(注:n表示斷點号)

    info breakpoints [n]

    info break [n]

二、設定觀察點(WatchPoint)

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

    watch <expr>

        為表達式(變量)expr設定一個觀察點。一量表達式值有變化時,馬上停住程式。

    rwatch <expr>

        當表達式(變量)expr被讀時,停住程式。

    awatch <expr>

        當表達式(變量)的值被讀或被寫時,停住程式。

    info watchpoints

        列出目前所設定了的所有觀察點。

三、設定捕捉點(CatchPoint)

    你可設定捕捉點來補捉程式運作時的一些事件。如:載入共享庫(動态連結庫)或是C++的異常。設定捕捉點的格式為:

    catch <event>

        當event發生時,停住程式。event可以是下面的内容:

        1、throw 一個C++抛出的異常。(throw為關鍵字)

        2、catch 一個C++捕捉到的異常。(catch為關鍵字)

        3、exec 調用系統調用exec時。(exec為關鍵字,目前此功能隻在HP-UX下有用)

        4、fork 調用系統調用fork時。(fork為關鍵字,目前此功能隻在HP-UX下有用)

        5、vfork 調用系統調用vfork時。(vfork為關鍵字,目前此功能隻在HP-UX下有用)

        6、load 或 load <libname> 載入共享庫(動态連結庫)時。(load為關鍵字,目前此功能隻在HP-UX下有用)

        7、unload 或 unload <libname> 解除安裝共享庫(動态連結庫)時。(unload為關鍵字,目前此功能隻在HP-UX下有用)

    tcatch <event>

        隻設定一次捕捉點,當程式停住以後,應點被自動删除.