1. 程式人生 > >用GDB除錯程式 Ubuntu中文

用GDB除錯程式 Ubuntu中文

               

導讀:

用GDB除錯程式出自Ubuntu中文目錄[隱藏]1 GDB概述 2 一個除錯示例 3 使用GDB 4 GDB的命令概貌 5 GDB中執行UNIX的shell程式 6 在GDB中執行程式 7 除錯已執行的程式 8 暫停/恢復程式執行 8.1 設定斷點(Break Points) 8.2 設定觀察點(WatchPoint) 8.3 設定捕捉點(CatchPoint) 8.4 維護停止點 8.5 停止條件維護 8.6 為停止點設定執行命令 8.7 斷點選單 8.8 恢復程式執行和單步除錯 8.9 訊號(Signals) 8.10 執行緒(Thread Stops) 9 檢視棧資訊 10 檢視源程式 10.1 顯示原始碼 10.2 搜尋原始碼 10.3 指定原始檔的路徑 10.4 原始碼的記憶體 11 檢視執行時資料 11.1 表示式 11.2 程式變數 11.3 陣列 11.4 輸出格式 11.5 檢視記憶體 11.6 自動顯示 11.7 設定顯示選項 11.8 歷史記錄 11.9 GDB環境變數 11.10 檢視暫存器 12 改變程式的執行 12.1 修改變數值 12.2 跳轉執行 12.3 產生訊號量 12.4 強制函式返回 12.5 強制呼叫函式 13 在不同語言中使用GDB 14 後記 15 相關詞條   用GDB除錯程式(zz) 作者:haoel (QQ是:753640,MSN是:

[email protected]) 來源:http://blog.csdn.net/haoel/archive/2003/07/02/2879.aspx [編輯] GDB概述GDB 是GNU開源組織釋出的一個強大的UNIX下的程式除錯工具。或許,各位比較喜歡那種圖形介面方式的,像VC、BCB等IDE的除錯,但如果你是在 UNIX平臺下做軟體,你會發現GDB這個除錯工具有比VC、BCB的圖形化偵錯程式更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。

一般來說,GDB主要幫忙你完成下面四個方面的功能:

啟動你的程式,可以按照你的自定義的要求隨心所欲的執行程式。 可讓被除錯的程式在你所指定的調置的斷點處停住。(斷點可以是條件表示式) 當程式被停住時,可以檢查此時你的程式中所發生的事。 動態的改變你程式的執行環境。 從上面看來,GDB和一般的除錯工具沒有什麼兩樣,基本上也是完成這些功能,不過在細節上,你會發現GDB這個除錯工具的強大,大家可能比較習慣了圖形化的除錯工具,但有時候,命令列的除錯?ぞ呷從凶磐夾位ぞ咚荒芡瓿傻墓δ堋H夢頤且灰豢蠢礎?

[編輯] 一個除錯示例源程式:tst.c

 1 #include <stdio.h>                                                                  2  3 int func(int n) 4 { 5     int sum=0,i; 6     for(i=1; i<=n; i++) 7     { 8         sum+=i; 9     }10     return sum;11 }12 13 14 int main()15 {16     int i;17     long result = 0;18     for(i=1; i<=100; i++)19     {20         result += i;21     }22 23     printf("result[1-100] = %ld /n", result );24     printf("result[1-250] = %d /n", func(250) );25     return 0;26 }27

編譯生成執行檔案:

$gcc -g -Wall tst.c -o tst

使用GDB除錯:

$ gdb tst   <---------- 啟動GDBGNU gdb 6.7.1-debianCopyright (C) 2007 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".(gdb) l 1   <-------------------- l命令相當於list,從第一行開始例出原碼。1       #include <stdio.h>23       int func(int n)4       {5               int sum=0,i;6               for(i=1; i<=n; i++)7               {8                       sum+=i;9               }10              return sum;(gdb)    <-------------------- 直接回車表示,重複上一次命令11      }121314      int main()15      {16              int i;17              long result = 0;18              for(i=1; i<=100; i++)19              {20   result += i;(gdb) break 16    <-------------------- 設定斷點,在源程式第16行處。Breakpoint 1 at 0x80483b2: file tst.c, line 16.(gdb) break func   <-------------------- 設定斷點,在函式func()入口處。Breakpoint 2 at 0x804837a: file tst.c, line 5.(gdb) info break   <-------------------- 檢視斷點資訊。Num Type           Disp Enb Address    What1   breakpoint     keep y   0x080483b2 in main at tst.c:162   breakpoint     keep y   0x0804837a in func at tst.c:5(gdb) r    <--------------------- 執行程式,run命令簡寫Starting program: /home/dbzhang/tst

Breakpoint 1, main () at tst.c:1717  long result = 0;(gdb) n     <--------------------- 單條語句執行,next命令簡寫。18  for(i=1; i<=100; i++)(gdb) n20   result += i;(gdb) n18  for(i=1; i<=100; i++)(gdb) n20   result += i;(gdb) c    <--------------------- 繼續執行程式,continue命令簡寫。Continuing.result[1-100] = 5050    <----------程式輸出。

Breakpoint 2, func (n=250) at tst.c:55  int sum=0,i;(gdb) n6  for(i=1; i<=n; i++)(gdb) p i   <--------------------- 列印變數i的值,print命令簡寫。$1 = -1074568236(gdb) n8   sum+=i;(gdb) n6  for(i=1; i<=n; i++)(gdb) p sum$2 = 1(gdb) n8   sum+=i;(gdb) p i$3 = 2(gdb) n6  for(i=1; i<=n; i++)(gdb) p sum$4 = 3(gdb) bt   <--------------------- 檢視函式堆疊。#0  func (n=250) at tst.c:6#1  0x080483f1 in main () at tst.c:24(gdb) finish   <--------------------- 退出函式。Run till exit from #0  func (n=250) at tst.c:60x080483f1 in main () at tst.c:2424  printf("result[1-250] = %d /n", func(250) );Value returned is $5 = 31375(gdb) c   <--------------------- 繼續執行。Continuing.result[1-250] = 31375    <----------程式輸出。

Program exited normally.   <--------程式退出,除錯結束。(gdb) q   <--------------------- 退出gdb。

好了,有了以上的感性認識,還是讓我們來系統地認識一下gdb吧。

[編輯] 使用GDB一般來說GDB主要除錯的是C/C++的程式。要除錯C/C++的程式,首先在編譯時,我們必須要把除錯資訊加到可執行檔案中。使用編譯器(cc/gcc/g++)的 -g 引數可以做到這一點。如:

$gcc -g -Wall hello.c -o hello$g++ -g -Wall hello.cpp -o hello

如果沒有-g,你將看不見程式的函式名、變數名,所代替的全是執行時的記憶體地址。當你用-g把除錯資訊加入之後,併成功編譯目的碼以後,讓我們來看看如何用gdb來除錯他。

啟動GDB的方法有以下幾種:

gdb <program> program也就是你的執行檔案,一般在當然目錄下。 gdb <program> core 用gdb同時除錯一個執行程式和core檔案,core是程式非法執行後core dump後產生的檔案。 gdb <program> <PID> 如果你的程式是一個服務程式,那麼你可以指定這個服務程式執行時的程序ID。gdb會自動attach上去,並除錯他。program應該在PATH環境變數中搜索得到。 GDB啟動時,可以加上一些GDB的啟動開關,詳細的開關可以用gdb -help檢視。我在下面只例舉一些比較常用的引數:

-symbols <file> -s <file> 從指定檔案中讀取符號表。 -se file 從指定檔案中讀取符號表資訊,並把他用在可執行檔案中。 -core <file> -c <file> 除錯時core dump的core檔案。 -directory <directory> -d <directory> 加入一個原始檔的搜尋路徑。預設搜尋路徑是環境變數中PATH所定義的路徑。 [編輯] GDB的命令概貌啟動gdb後,就你被帶入gdb的除錯環境中,就可以使用gdb的命令開始除錯程式了,gdb的命令可以使用help命令來檢視,如下所示:

$ gdbGNU gdb 6.7.1-debianCopyright (C) 2007 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "i486-linux-gnu".(gdb) helpList of classes of commands:

aliases -- Aliases of other commandsbreakpoints -- Making program stop at certain pointsdata -- Examining datafiles -- Specifying and examining filesinternals -- Maintenance commandsobscure -- Obscure featuresrunning -- Running the programstack -- Examining the stackstatus -- Status inquiriessupport -- Support facilitiestracepoints -- Tracing of program execution without stopping the programuser-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.Type "help all" for the list of all commands.Type "help" followed by command name for full documentation.Type "apropos word" to search for commands related to "word".Command name abbreviations are allowed if unambiguous.(gdb)

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

gdb中,輸入命令時,可以不用打全命令,只用打命令的前幾個字元就可以了,當然,命令的?凹父鱟址Ω靡曛咀乓桓鑫ㄒ壞拿睿贚inux下,你可以敲擊兩次TAB鍵來補齊命令的全稱,如果有重複的,那麼gdb會把其例出來。

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

(gdb) b funcBreakpoint 1 at 0x804837a: file tst.c, line 5.

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

(gdb) bbacktrace break bt(gdb)

示例三:只記得函式的字首,可以這樣:

(gdb) b make_ <按TAB鍵>(再按下一次TAB鍵,你會看到:)make_a_section_from_file make_environmake_abs_section make_function_typemake_blockvector make_pointer_typemake_cleanup make_reference_typemake_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

[編輯] 除錯已執行的程式兩種方法:

在UNIX下用ps檢視正在執行的程式的PID(程序ID),然後用gdb <program> PID格式掛接正在執行的程式。 先用gdb <program>關聯上原始碼,並進行gdb,在gdb中用attach命令來掛接程序的PID。並用detach來取消掛接的程序。 [編輯] 暫停/恢復程式執行除錯程式中,暫停程式執行是必須的,GDB可以方便地暫停程式的執行。你可以設定程式的在哪行停住,在什麼條件下停住,在收到?裁蔥藕攀蓖M鵲取R員閿諛悴榭叢誦惺鋇謀淞浚約霸誦惺鋇牧鞽獺?

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

在gdb中,我們可以有以下幾種暫停方式:斷點(BreakPoint)、觀察點(Watch Point)、捕捉點(Catch Point)、訊號(Signals)、執行緒停止(Thread Stops)。如果要恢復程式執行,可以使用c或是 continue命令。

[編輯] 設定斷點(Break Points)我們用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)觀察點一般來觀察某個表示式(變數也是一種表示式)的值是否有變化了,如果有變化,?砩賢W〕絛頡N頤怯邢旅嫻募鋼址椒ɡ瓷柚黴鄄斕悖?

watch <expr> 為表示式(變數)expr設定一個觀察點。一量表達式值有變化時,馬上停住程式。 rwatch <expr> 當表示式(變數)expr被讀時,停住程式。 awatch <expr> 當表示式(變數)的值被讀或被寫時,停住程式。 info watchpoints 列出當前所設定了的所有觀察點。 [編輯] 設定捕捉點(CatchPoint)   你可設定捕捉點來補捉程式執行時的一些事件。如:載入共享庫(動態連結庫)或是C++的異常。設定捕捉點的格式為: 

catch <event> 當event發生時,停住程式。event可以是下面的內容:

throw 一個C++丟擲的異常。(throw為關鍵字) catch 一個C++捕捉到的異常。(catch為關鍵字) exec 呼叫系統呼叫exec時。(exec為關鍵字,目前此功能只在HP-UX下有用) fork 呼叫系統呼叫fork時。(fork為關鍵字,目前此功能只在HP-UX下有用) vfork 呼叫系統呼叫vfork時。(vfork為關鍵字,目前此功能只在HP-UX下有用) load 或 load <libname> 載入共享庫(動態連結庫)時。(load為關鍵字,目前此功能只在HP-UX下有用) unload 或 unload <libname> 解除安裝共享庫(動態連結庫)時。(unload為關鍵字,目前此功能只在HP-UX下有用) tcatch <event> 只設置一次捕捉點,當程式停住以後,應點被自動刪除。

[編輯] 維護停止點上面說了如何設定程式的停止點,GDB中的停止點也就是上述的三類。在GDB中,如果你覺得已定義好的停止點沒有用了,你可以使用delete、clear、disable、enable這幾個命令來進行維護。

clear 清除所有的已定義的停止點。 clear <function> clear <filename:function> 清除所有設定在函式上的停止點。 clear <linenum> clear <filename:linenum> 清除所有設定在指定行上的停止點。 delete [breakpoints] [range...] 刪除指定的斷點,breakpoints為斷點號。如果不指定斷點號,則表示刪除所有的斷點。range 表示斷點號的範圍(如:3-7)。其簡寫命令為d。

比刪除更好的一種方法是disable停止點,disable了的停止點,GDB不會刪除,當你還需要時,enable即可,就好像回收站一樣。

disable [breakpoints] [range...] disable所指定的停止點,breakpoints為停止點號。如果什麼都不指定,表示disable所有的停止點。簡寫命令是dis. enable [breakpoints] [range...] enable所指定的停止點,breakpoints為停止點號。 enable [breakpoints] once range... enable所指定的停止點一次,當程式停止後,該停止點馬上被GDB自動disable。 enable [breakpoints] delete range... enable所指定的停止點一次,當程式停止後,該停止點馬上被GDB自動刪除。 [編輯] 停止條件維護前面在說到設定斷點時,我們提到過可以設定一個條件,當條件成立時,程式自動停止,?饈且桓齜淺G看蟮墓δ埽飫錚蟻胱潘鄧嫡飧鎏跫南喙匚っ睢R話憷此擔?點設定一個條件,我們使用if關鍵詞,後面跟其斷點條件。並且,條件設定好後,我們可以用condition命令來修改斷點的條件。(只有break和watch命令支援if,catch目前暫不支援if)

condition <bnum> <expression> 修改斷點號為bnum的停止條件為expression。 condition <bnum> 清除斷點號為bnum的停止條件。

還有一個比較特殊的維護命令ignore,你可以指定程式執行時,忽略停止條件幾次。

ignore <bnum> <count> 表示忽略斷點號為bnum的停止條件count次。 [編輯] 為停止點設定執行命令我們可以使用GDB提供的command命令來設定停止點的執行命令。也就是說,當執行的程式在被停止住時,我們可以讓其自?誦幸恍┍鸕拿睿夂苡欣凶遠魘浴6曰贕DB的自動化除錯是一個強大的支援。

commands [bnum]... command-list ...end

為斷點號bnum指寫一個命令列表。當程式被該斷點停住時,gdb會依次執行命令列表中的命令。例如:

break foo if x>0commandsprintf "x is %d/n",xcontinueend

斷點設定在函式foo中,斷點條件是x>0,如果程式被斷住後,也就是,一旦x的值在foo函式中大於0,GDB會自動打印出x的值,並繼續執行程式。

如果你要清除斷點上的命令序列,那麼只要簡單的執行一下commands命令,並直接在打個end就行了。

[編輯] 斷點選單在C++中,可能會重複出現同一個名字的函式若干次(函式過載),在這種情況下,break <function>不能告訴GDB要停在哪個函式的入口。當然,你可以使用break <function(type)>也就是把函式的引數型別告訴GDB,以指定一個函式。否則的話,GDB會給你列出一個斷點選單供你選擇你所需要的斷點。你只要輸入你選單列表中的編號就可?粵恕H紓?

(gdb) b String::after[0] cancel[1] all[2] file:String.cc; line number:867[3] file:String.cc; line number:860[4] file:String.cc; line number:875[5] file:String.cc; line number:853[6] file:String.cc; line number:846[7] file:String.cc; line number:735> 2 4 6Breakpoint 1 at 0xb26c: file String.cc, line 867.Breakpoint 2 at 0xb344: file String.cc, line 875.Breakpoint 3 at 0xafcc: file String.cc, line 846.Multiple breakpoints were set.Use the "delete" command to delete unwantedbreakpoints.(gdb)

可見,GDB列出了所有after的過載函式,你可以選一下列表編號就行了。0表示放棄設定斷點,1表示所有函式都設定斷點。

[編輯] 恢復程式執行和單步除錯當程式被停住了,你可以用continue命令恢復程式的執行直到程式結束,或下一個斷點到來。也可以使用step或next命令單步跟蹤程式。

continue [ignore-count]c [ignore-count]fg [ignore-count] 恢復程式執行,直到程式結束,或是下一個斷點到來。ignore-count表示忽略其後的斷點次數。continue,c,fg三個命令都是一樣的意思。 step <count> 單步跟蹤,如果有函式呼叫,他會進入該函式。進入函式的前提是,此函式被編譯有debug資訊。很像VC等工具中的step in。後面可以加count也可以不加,不加表示一條條地執行,加表示執行後面的count條指令,然後再停住。 next <count> 同樣單步跟蹤,如果有函式呼叫,他不會進入該函式。很像VC等工具中的step over。後面可以加count也可以不加,不加表示一條條地執行,加表示執行後面的count條指令,然後再停住。 set step-modeset step-mode on 開啟step-mode模式,於是,在進行單步跟蹤時,程式不會因為沒有debug資訊而不停住。這個引數有很利於檢視機器碼。 set step-mod off 關閉step-mode模式。 finish 執行程式,直到當前函式完成返回。並列印函式返回時的堆疊地址和返回值及引數值等信?ⅰ?until 或 u 當你厭倦了在一個迴圈體內單步跟蹤時,這個命令可以執行程式直到退出迴圈體。 stepi 或 sinexti 或 ni 單步跟蹤一條機器指令!一條程式程式碼有可能由數條機器指令完成,stepi和nexti可以單步執行機器指令。與之一樣有相同功能的命令是 “display/i $pc” ,當執行完這個命令後,單步跟蹤會在打出程式程式碼的同時打出機器指令(也就是彙編代?耄?[編輯] 訊號(Signals)訊號是一種軟中斷,是一種處理非同步事件的方法。一般來說,作業系統都支援許多訊號。?繞涫?UNIX,比較重要應用程式一般都會處理訊號。UNIX定義了許多訊號,比如SIGINT表示中斷字元訊號,也就是Ctrl+C的訊號,SIGBUS表示硬體故障的訊號;SIGCHLD表示子程序狀態改變訊號;SIGKILL表示終止程式執行的訊號,等等。訊號量程式設計是UNIX下非常重要的一種技術。

GDB有能力在你除錯程式的時候處理任何一種訊號,你可以告訴GDB需要處理哪一種訊號。你可以要求GDB收到你所指定的訊號時,馬上停住正在執行的程式,以供你進行除錯。你可以用GDB的handle命令來完成這一功能。

handle <signal> <keywords...>

在GDB中定義一個訊號處理。訊號<signal>可以以SIG開頭或不以SIG開頭,可以用定義一個要處理訊號的範圍(如:SIGIO- SIGKILL,表示處理從SIGIO訊號到SIGKILL的訊號,其中包括SIGIO,SIGIOT,SIGKILL三個訊號),也可以使用關鍵字 all來標明要處理所有的訊號。一旦被除錯的程式接收到訊號,執行程式馬上會被GDB停住,以供除錯。其<keywords>可以是以下幾種關鍵字的一個或多個。

nostop 當被除錯的程式收到訊號時,GDB不會停住程式的執行,但會打出訊息告訴你收到這種訊號。 stop 當被除錯的程式收到訊號時,GDB會停住你的程式。 print 當被除錯的程式收到訊號時,GDB會顯示出一條資訊。 noprint 當被除錯的程式收到訊號時,GDB不會告訴你收到訊號的資訊。 passnoignore 當被除錯的程式收到訊號時,GDB不處理訊號。這表示,GDB會把這個訊號交給被除錯程式會處理。 nopassignore 當被除錯的程式收到訊號時,GDB不會讓被除錯程式來處理這個訊號。 info signalsinfo handle 檢視有哪些訊號在被GDB檢測中。 [編輯] 執行緒(Thread Stops)如果你程式是多執行緒的話,你可以定義你的斷點是否在所有的執行緒上,或是在某個特定的?叱獺DB很容易幫你完成這一工作。

break <linespec> thread <threadno>break <linespec> thread <threadno> if ...

linespec指定了斷點設定在的源程式的行號。threadno指定了執行緒的ID,注意,這個ID是GDB分配的,你可以通過“info threads”命令來檢視正在執行程式中的執行緒資訊。如果你不指定thread <threadno>則表示你的斷點設在所有執行緒上面。你還可以為某執行緒指定斷點條件。如:

(gdb) break frik.c:13 thread 28 if bartab > lim

當你的程式被GDB停住時,所有的執行執行緒都會被停住。這方便你你檢視執行程式的總體情況。而在你恢復?絛蛟誦惺保械南叱桃不岜換指叢誦小D橋率侵鶻淘詒壞ゲ降魘允薄?

[編輯] 檢視棧資訊當程式被停住了,你需要做的第一件事就是檢視程式是在哪裡停住的。當你的程式呼叫了?桓齪牡刂罰問詰木植勘淞慷薊岜謊谷搿罷弧保⊿tack)中。你可以用GDB命令來檢視當前的棧中的資訊。

下面是一些檢視函式呼叫棧資訊的GDB命令:

backtracebt 列印當前的函式呼叫棧的所有資訊。如: (gdb) bt#0  func (n=250) at tst.c:6#1  0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30#2  0x400409ed in __libc_start_main () from /lib/libc.so.6     

從上可以看出函式的呼叫棧資訊:__libc_start_main --> main() --> func()

backtrace <n>bt <n> n是一個正整數,表示只打印棧頂上n層的棧資訊。 backtrace <-n>bt <-n> -n表一個負整數,表示只打印棧底下n層的棧資訊。 如果你要檢視某一層的資訊,你需要在切換當前的棧,一般來說,程式停止時,最頂層的?瘓褪塹鼻罷唬綣鬩榭湊幌旅娌愕南晗感畔ⅲ紫紉齙氖喬謝壞鼻罷弧?

frame <n>f <n> n是一個從0開始的整數,是棧中的層編號。比如:frame 0,表示棧頂,frame 1,表示棧的第二層。 up <n> 表示向棧的上面移動n層,可以不打n,表示向上移動一層。 down <n> 表示向棧的下面移動n層,可以不打n,表示向下移動一層。

上面的命令,都會打印出移動到的棧層的資訊。如果你不想讓其打出資訊。你可以使用這?雒睿?

select-frame <n> 對應於 frame 命令。up-silently <n> 對應於 up 命令。down-silently <n> 對應於 down 命令。

檢視當前棧層的資訊,你可以用以下GDB命令:

frame 或 f 會打印出這些資訊:棧的層編號,當前的函式名,函式引數值,函式所在檔案及行號,函?蔥械降撓錁洹?info frameinfo f 這個命令會打印出更為詳細的當前棧層的資訊,只不過,大多數都是執行時的內內地址。?熱紓漢刂罰饔煤牡刂罰壞饔煤牡刂罰殼暗暮怯墒裁囪某絛蠐鋂?寫成的、函式引數地址及值、區域性變數的地址等等。如: (gdb) info fStack level 0, frame at 0xbffff5d4:eip = 0x804845d in func (tst.c:6); saved eip 0x8048524called by frame at 0xbffff60csource language c.Arglist at 0xbffff5d4, args: n=250Locals at 0xbffff5d4, Previous frame's sp is 0x0Saved registers:ebp at 0xbffff5d4, eip at 0xbffff5d8           

info args 打印出當前函式的引數名及其值。 info locals 打印出當前函式中所有區域性變數及其值。 info catch 打印出當前的函式中的異常處理資訊。 [編輯] 檢視源程式[編輯] 顯示原始碼GDB 可以打印出所除錯程式的原始碼,當然,在程式編譯時一定要加上-g的引數,把源程式資訊編譯到執行檔案中。不然就看不到源程式了。當程式停下來以後,GDB會報告程式停在了那個檔案的第幾行上。你可以用list命令來列印程式的原始碼。還是來看一看檢視原始碼的GDB命令吧。

list <linenum> 顯示程式第linenum行的周圍的源程式。 list <function> 顯示函式名為function的函式的源程式。 list 顯示當前行後面的源程式。 list - 顯示當前行前面的源程式。 一般是列印當前行的上5行和下5行,如果顯示函式是是上2行下8行,預設是10行,當然,你也可以定製顯示的範圍,使用下面命令可以設定一次顯示源程式的行數。

set listsize <count> 設定一次顯示原始碼的行數。 show listsize 檢視當前listsize的設定。 list命令還有下面的用法:

list <first>, <last> 顯示從first行到last行之間的原始碼。 list , <last> 顯示從當前行到last行之間的原始碼。 list + 往後顯示原始碼。 一般來說在list後面可以跟以下這們的引數:

<linenum>   行號。<+offset>   當前行號的正偏移量。<-offset>   當前行號的負偏移量。<filename:linenum>  哪個檔案的哪一行。<function>  函式名。<filename:function> 哪個檔案中的哪個函式。<*address>  程式執行時的語句在記憶體中的地址。 

[編輯] 搜尋原始碼不僅如此,GDB還提供了原始碼搜尋的命令:

forward-search <regexp>search <regexp> 向前面搜尋。 reverse-search <regexp> 全部搜尋。 其中,<regexp>就是正則表示式,也主一個字串的匹配模式,關於正則表示式,我就不在這裡講了,還請各位檢視相關資料。

[編輯] 指定原始檔的路徑某些時候,用-g編譯過後的執行程式中只是包括了原始檔的名字,沒有路徑名。GDB提供了可以讓你指定原始檔的路徑的命令,以便GDB進行搜尋。

directory <dirname ... >dir <dirname ... > 加一個原始檔路徑到當前路徑的前面。如果你要指定多個路徑,UNIX下你可以使用“:”,Windows下你可以使用“;”。 directory 清除所有的自定義的原始檔搜尋路徑資訊。 show directories 顯示定義了的原始檔搜尋路徑。 [編輯] 原始碼的記憶體你可以使用info line命令來檢視原始碼在記憶體中的地址。info line後面可以跟“行號”,“函式名”,“檔名:行號”,“檔名:函式名”,這個命令會?蠐〕鏊付ǖ腦綽朐讜誦惺鋇哪詿嫻刂罰紓?

(gdb) info line tst.c:funcLine 5 of "tst.c" starts at address 0x8048456 <func+6> and ends at 0x804845d <func+13>.

還有一個命令(disassemble)你可以檢視源程式的當前執行時的機器碼,這個命令會把目前記憶體中的指令dump出來。如下面的示例表示檢視函式func的彙編程式碼。

(gdb) disassemble funcDump of assembler code for function func:0x8048450 <func>:       push   %ebp0x8048451 <func+1>:     mov    %esp,%ebp0x8048453 <func+3>:     sub    $0x18,%esp0x8048456 <func+6>:     movl   $0x0,0xfffffffc(%ebp)0x804845d <func+13>:    movl   $0x1,0xfffffff8(%ebp)0x8048464 <func+20>:    mov    0xfffffff8(%ebp),%eax0x8048467 <func+23>:    cmp    0x8(%ebp),%eax0x804846a <func+26>:    jle    0x8048470 <func+32>0x804846c <func+28>:    jmp    0x8048480 <func+48>0x804846e <func+30>:    mov    %esi,%esi0x8048470 <func+32>:    mov    0xfffffff8(%ebp),%eax0x8048473 <func+35>:    add    %eax,0xfffffffc(%ebp)0x8048476 <func+38>:    incl   0xfffffff8(%ebp)0x8048479 <func+41>:    jmp    0x8048464 <func+20>0x804847b <func+43>:    nop0x804847c <func+44>:    lea    0x0(%esi,1),%esi0x8048480 <func+48>:    mov    0xfffffffc(%ebp),%edx0x8048483 <func+51>:    mov    %edx,%eax0x8048485 <func+53>:    jmp    0x8048487 <func+55>0x8048487 <func+55>:    mov    %ebp,%esp0x8048489 <func+57>:    pop    %ebp0x804848a <func+58>:    retEnd of assembler dump.

[編輯] 檢視執行時資料在你除錯程式時,當程式被停住時,你可以使用print命令(簡寫命令為p),或是同義命令inspect來檢視當前程式的執行資料。print命令的格式是:

print <expr>print /<f> <expr>

<expr>是表示式,是你所除錯的程式的語言的表示式(GDB可以除錯多種程式語言),<f>是輸出的格式,比如,如果要把表示式按16進位制的格式輸出,那麼就是/x。

[編輯] 表示式print和許多GDB的命令一樣,可以接受一個表示式,GDB會根據當前的程式執行的資料來計算這個表示式,既然是表示式,那麼就可以是當前程式?誦兄械腸onst常量、變數、函式等內容。可惜的是GDB不能使用你在程式中所定義的巨集。

表示式的語法應該是當前所除錯的語言的語法,由於C/C++是一種大眾型的語言,所以,本文中的例子都是關於C/C++的。(而關於用GDB除錯其它語言的章節,我將在後面介紹)

在表示式中,有幾種GDB所支援的操作符,它們可以用在任何一種語言中。

@

是一個和陣列有關的操作符,在後面會有更詳細的說明。 ::

指定一個在檔案或是一個函式中的變數。 {<type>} <addr>

表示一個指向記憶體地址<addr>的型別為type的一個物件。 [編輯] 程式變數在GDB中,你可以隨時檢視以下三種變數的值:

全域性變數(所有檔案可見的) 靜態全域性變數(當前檔案可見的) 區域性變數(當前Scope可見的) 如果你的區域性變數和全域性變數發生衝突(也就是重名),一般情況下是區域性變數會隱藏全?直淞浚簿褪撬擔綣桓鋈直淞亢鴕桓齪械木植勘淞客保綣鼻巴V溝閽?函式中,用print顯示出的變數的值會是函式中的區域性變數的值。如果此時你想檢視全域性變數的值時,你可?允褂謾?:”操作符:

file::variablefunction::variable

可以通過這種形式指定你所想檢視的變數,是哪個檔案中的或是哪個函式中的。例如,查?次募2.c中的全域性變數x的值:

(gdb) p 'f2.c'::x

當然,“::”操作符會和C++中的發生衝突,GDB能自動識別“::” 是否C++的操作符,所以你不必擔心在除錯C++程式時會出現異常。

另外,需要注意的是,如果你的程式編譯時開啟了優化選項,那麼在用GDB除錯被優化過的程式時,可能會發生某些變數不能訪問,或是取值錯誤碼的情況。這個是?苷5模蛭嘔絛蚧嶸靖哪愕某絛潁砟慍絛虻撓錁淥承潁蕹恍┪摶庖宓謀淞?等,所以在GDB除錯這種程式時,執行時的指令和你所編寫指令就有不一樣,也就會出現你所想象不到的?峁6願墩庵智榭鍪保枰詒嘁氤絛蚴憊乇氈嘁胗嘔R話憷此擔負跛械謀嘁肫鞫?支援編譯優化的開關,例如,GNU 的C/C++編譯器GCC,你可以使用“-gstabs”選項來解決這個問題。關於編譯器的引數,還請檢視編譯器的使用說明文件。

[編輯] 陣列有時候,你需要檢視一段連續的記憶體空間的值。比如陣列的一段,或是動態分配的資料的?笮 D憧梢允褂肎DB的“@”操作符,“@”的左邊是第一個記憶體的地址的值,“@”的右邊則你你想檢視記憶體的長度。例如,你的程式中有這樣的語句:

int *array = (int *) malloc (len * sizeof (int));     

於是,在GDB除錯過程中,你可以以如下命令顯示出這個動態陣列的取值:

@的左邊是陣列的首地址的值,也就是變數array所指向的內容,右邊則是資料的長度,其儲存在變數len中,其輸出結果,大約是下面這個樣子的:

(gdb) p *[email protected]$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}

如果是靜態陣列的話,可以直接用print陣列名,就可以顯示陣列中所有資料的內容了。

[編輯] 輸出格式一般來說,GDB會根據變數的型別輸出變數的值。但你也可以自定義GDB的輸出的格式。例如,你想輸出一個整數的十六進位制,或是二進位制來檢視這個整型變數的?械奈壞那榭觥R齙秸庋憧梢允褂肎DB的資料顯示格式:

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

(gdb) p i$21 = 101   (gdb) p/a i$22 = 0x65(gdb) p/c i$23 = 101 'e'(gdb) p/f i$24 = 1.41531145e-43(gdb) p/x i$25 = 0x65(gdb) p/t i$26 = 1100101

[編輯] 檢視記憶體你可以使用examine命令(簡寫是x)來檢視記憶體地址中的值。x命令的語法如下所示:

x/<n/f/u> <addr> 

n、f、u是可選的引數。

n 是一個正整數,表示顯示記憶體的長度,也就是說從當前地址向後顯示幾個地址的內容。 f 表示顯示的格式,參見上面。如果地址所指的是字串,那麼格式可以是s,如果地十是指令地址,那麼格式可以是i。 u 表示從當前地址往後請求的位元組數,如果不指定的話,GDB預設是4個bytes。u引數可以用下面的字元來代替,b表示單位元組,h表示雙位元組,w表示四位元組,g表示八位元組。當我們指定了位元組長度後,GDB會從指記憶體定的記憶體地址開始,讀寫指定位元組,並把其當作一個值取出來。 <addr>表示一個記憶體地址。

n/f/u三個引數可以一起使用。例如:

命令:x/3uh 0x54320 表示,從記憶體地址0x54320讀取內容,h表示以雙位元組為一個單位,3表示三個單位,u表示按十六進位制顯示。

[編輯] 自動顯示你可以設定一些自動顯示的變數,當程式停住時,或是在你單步跟蹤時,這些變數會自動?允盡O喙氐腉DB命令是display。

display <expr>display/<fmt> <expr>display/<fmt> <addr>

expr是一個表示式,fmt表示顯示的格式,addr表示記憶體地址,當你用display設定好了一個或多個表示式後,只要你的程式被停下來,GDB會自動顯示你所設定的這些表示式的值。

格式i和s同樣被display支援,一個非常有用的命令是:

display/i $pc

$pc是GDB的環境變數,表示著指令的地址,/i則表示輸出格式為機器指令碼,也就是彙編。於是當程式停下後,就會出現原始碼和機器?噶盥胂嘍雜Φ那樾危饈且桓齪苡幸饉嫉墓δ堋?

下面是一些和display相關的GDB命令:

undisplay <dnums...>delete display <dnums...>

刪除自動顯示,dnums意為所設定好了的自動顯式的編號。如果要同時刪除幾個,編號可以用空格分隔,如果要?境桓齜段詰謀嗪牛梢雜眉鹺瘧硎荊ㄈ紓?-5)

disable display <dnums...>enable display <dnums...>

disable和enalbe不刪除自動顯示的設定,而只是讓其失效和恢復。

info display

檢視display設定的自動顯示的資訊。GDB會打出一張表格,向你報告當然除錯中設定了多少個自動顯示設定,其中包括,設定的編?牛澩鍤劍欠馿nable。

[編輯] 設定顯示選項GDB中關於顯示的選項比較多,這裡我只例舉大多數常用的選項。

set print addressset print address on 開啟地址輸出,當程式顯示函式資訊時,GDB會顯出函式的引數地址。系統預設為開啟的,如: (gdb) f#0  set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>")    at input.c:530530         if (lquote != def_lquote)

set print address off 關閉函式的引數地址顯示,如: (gdb) set print addr off(gdb) f#0  set_quotes (lq="<<", rq=">>") at input.c:530530         if (lquote != def_lquote)

show print address 檢視當前地址顯示選項是否開啟。 set print arrayset print array on 開啟陣列顯示,開啟後當陣列顯示時,每個元素佔一行,如果不開啟的話,每個元素則以?漢歐指簟U飧鮁∠釒鮮槍乇盞摹S脛喙氐牧礁雒釗縵攏揖筒輝俁嗨盜恕?set print array offshow print arrayset print elements <number-of-elements> 這個選項主要是設定陣列的,如果你的陣列太大了,那麼就可以指定一個<number-of-elements>來指定資料顯示的最大長度,當到達這個長度時,GDB就不再往下顯示了。如果設定為0,則表示不限制。 show print elements 檢視print elements的選項資訊。 set print null-stop <on/off> 如果打開了這個選項,那麼當顯示字串時,遇到結束符則停止顯示。這個選項預設為off。 set print pretty on 如果開啟printf pretty這個選項,那麼當GDB顯示結構體時會比較漂亮。如: $1 = {  next = 0x0,  flags = {    sweet = 1,    sour = 1  },  meat = 0x54 "Pork"}

set print pretty off 關閉printf pretty這個選項,GDB顯示結構體時會如下顯示: $1 = {next = 0x0, flags = {sweet = 1, sour = 1}, meat = 0x54 "Pork"}         

show print pretty 檢視GDB是如何顯示結構體的。 set print sevenbit-strings <on/off> 設定字元顯示,是否按“/nnn”的格式顯示,如果開啟,則字串或字元資料按/nnn顯示,如“/065”。 show print sevenbit-strings 檢視字元顯示開關是否開啟。 set print union <on/off> 設定顯示結構體時,是否顯式其內的聯合體資料。例如有以下資料結構: typedef enum {Tree, Bug} Species;typedef enum {Big_tree, Acorn, Seedling} Tree_forms;typedef enum {Caterpillar, Cocoon, Butterfly}              Bug_forms;

struct thing {  Species it;  union {    Tree_forms tree;    Bug_forms bug;  } form;};

struct thing foo = {Tree, {Acorn}};

當開啟這個開關時,執行 p foo 命令後,會如下顯示:

$1 = {it = Tree, form = {tree = Acorn, bug = Cocoon}}     

當關閉這個開關時,執行 p foo 命令後,會如下顯示:

$1 = {it = Tree, form = {...}}

show print union 檢視聯合體資料的顯示方式 set print object <on/off>:在C++中,如果一個物件指標指向其派生類,如果開啟這個選項,GDB會自動按照虛方法呼叫的規則顯示輸出,如果關閉這個選項的話,GDB就不管虛擬函式表了。這個選項預設是off。 show print object 檢視物件選項的設定。 set print static-members <on/off> 這個選項表示,當顯示一個C++物件中的內容是,是否顯示其中的靜態資料成員。預設是on。 show print static-members 檢視靜態資料成員選項設定。 set print vtbl <on/off> 當此選項開啟時,GDB將用比較規整的格式來顯示虛擬函式表時。其預設是關閉的。 show print vtbl 檢視虛擬函式顯示格式的選項。 [編輯] 歷史記錄當你用GDB的print檢視程式執行時的資料時,你每一個print都會被GDB記錄下來。GDB會以$1, $2, $3 .....這樣的方式為你每一個print命令編上號。於是,你可以使用這個編號訪問以前的表示式,如$1。這個功能所帶來的好處是,如果你先前輸入了一個比較長的表示式,如果你還想檢視這?霰澩鍤降鬧擔憧梢允褂美芳鍬祭捶夢剩∪チ酥馗詞淙搿?

[編輯] GDB環境變數你可以在GDB的除錯環境中定義自己的變數,用來儲存一些除錯程式中的執行資料。要定義一個GDB的變數很簡單隻需。使用GDB的set命令。GDB的環境變數和UNIX一樣,也是以$起頭。如:

set $foo = *object_ptr

使用環境變數時,GDB會在你第一次使用時建立這個變數,而在以後的使用中,則直接對其賦值。環境變數沒有?嘈停憧梢願肪潮淞慷ㄒ迦我壞睦嘈汀0ń峁固搴褪欏?

show convenience 該命令檢視當前所設定的所有的環境變數。 這是一個比較強大的功能,環境變數和程式變數的互動使用,將使得程式除錯更為靈活便?蕁@紓?

set $i = 0print bar[$i++]->contents

於是,當你就不必,print bar[0]->contents, print bar[1]->contents地輸入命令了。輸入這樣的命令後,只用敲回車,重複執行上一條語句,環境變數會自動?奐櫻傭瓿芍鷥鍪涑齙墓δ堋?

[編輯] 檢視暫存器要檢視暫存器的值,很簡單,可以使用如下命令:

info registers 檢視暫存器的情況。(除了浮點暫存器) info all-registers 檢視所有暫存器的情況。(包括浮點暫存器) info registers <regname ...> 檢視所指定的暫存器的情況。 暫存器中放置了程式執行時的資料,比如程式當前執行的指令地址(ip),程式的當前堆疊地址(sp)等等。你同樣可以使用print命令來訪問暫存器的情況,只需要在暫存器名字前加一個$符號就可以了。如:p $eip。

[編輯] 改變程式的執行一旦使用GDB掛上被除錯程式,當程式執行起來後,你可以根據自己的除錯思路來動態地在GDB中更改當前被除錯程式的執行線路或是其變數的值,這個強大的功能能夠讓你更好的除錯?愕某絛潁熱紓憧梢栽誄絛虻囊淮臥誦兄凶弒槌絛虻乃蟹種А?

[編輯] 修改變數值修改被除錯程式執行時的變數值,在GDB中很容易實現,使用GDB的print命令即可完成。如:

(gdb) print x=4

x=4這個表示式是C/C++的語法,意為把變數x的值修改為4,如果你當前除錯的語言是Pascal,那麼你可以使用Pascal的語法:x:=4。

在某些時候,很有可能你的變數和GDB中的引數衝突,如:

(gdb) whatis widthtype = double(gdb) p width$4 = 13(gdb) set width=47Invalid syntax in expression.

因為,set width是GDB的命令,所以,出現了“Invalid syntax in expression”的設定錯誤,此時,你可以使用set var命令來告訴GDB,width不是你GDB的引數,而是程式的變數名,如:

(gdb) set var width=47

另外,還可能有些情況,GDB並不報告這種錯誤,所以保險起見,在你改變程式變數取值時,最好都使用set var格式的GDB命令。

[編輯] 跳轉執行一般來說,被除錯程式會按照程式程式碼的執行順序依次執行。GDB提供了亂序執行的功能,也就是說,GDB可以修改程式的執行順序,可以讓程式執行隨意跳躍。這個功能可以由GDB的jump命令來完:

jump <linespec> 指定下一條語句的執行點。<linespce>可以是檔案的行號,可以是file:line格式,可以是+num這種偏移量格式。表式著下一條執行語句從哪裡開始。 jump <address> 這裡的<address>是程式碼行的記憶體地址。 注意,jump命令不會改變當前的程式棧中的內容,所以,當你從一個函式跳到另一個函式時,當函式?誦型攴禱厥苯械徊僮魘北厝換岱⑸砦螅贍芙峁故欠淺F婀值模踔劣誆絛?Core Dump。所以最好是同一個函式中進行跳轉。

熟悉彙編的人都知道,程式執行時,有一個暫存器用於儲存當前程式碼所在的記憶體地址。所?裕琷ump命令也就是改變了這個暫存器中的值。於是,你可以使用“set $pc”來更改跳轉執行的地址。如:

set $pc = 0x485

[編輯] 產生訊號量使用singal命令,可以產生一個訊號量給被除錯的程式。如:中斷訊號Ctrl+C。這非常方便於程式的除錯,可以在程式執行的任意位置設定斷點,並在該斷點用GDB產生一個訊號量,這種精確地在某處產生訊號非常有利程式的除錯。

語法是:signal <singal>,UNIX的系統訊號量通常從1到15。所以<singal>取值也在這個範圍。

single命令和shell的kill命令不同,系統的kill命令發訊號給被除錯程式時,是由GDB截獲的,而single命令所發出一訊號則是直接發給被除錯程式的。

[編輯] 強制函式返回如果你的除錯斷點在某個函式中,並還有語句沒有執行完。你可以使用return命令強制函式忽略還沒有執行的語句並返回。

returnreturn <expression>   使用return命令取消當前函式的執行,並立即返回,如果指定了<expression>,那麼該表示式的值會被認作函式的返回值。 

[編輯] 強制呼叫函式call <expr>

表示式中可以一是函式,以此達到強制呼叫函式的目的。並顯示函式的返回值,如果函式?禱刂凳莢oid,那麼就不顯示。

另一個相似的命令也可以完成這一功能——print,print後面可以跟表示式,所以也可以用他來呼叫函式,print和call的不同是,如果函式返回void,call則不顯示,print則顯示函式返回值,並把該值存入歷史資料中。

[編輯] 在不同語言中使用GDBGDB支援下列語言:C, C++, Fortran, PASCAL, Java, Chill, assembly, 和 Modula-2。一般說來,GDB會根據你所除錯的程式來確定當然的除錯語言,比如:發現檔名字尾為“.c”的,GDB會認為是C程式。檔名字尾為 “.C, .cc, .cp, .cpp, .cxx, .c++”的,GDB會認為是C++程式。而字尾是“.f, .F”的,GDB會認為是Fortran程式,還有,字尾為如果是“.s, .S”的會認為是組合語言。

也就是說,GDB會根據你所除錯的程式的語言,來設定自己的語言環境,並讓GDB的命令跟著語言環境的改變而改變。比如一些GDB命令需要用到表示式或變數時,這些表示式或變數的語法,完全是根據當前的語言環境而?謀淶摹@鏑/C++中對指標的語法是*p,而在Modula-2中則是p^。並且,如果你當前的程式是由幾種不同語言一同編譯成的,那到在除錯過程中,GDB也能根據不同的語言自動地切換語言環境。這種跟著語言環境而改變的功能,真是體貼開?⑷嗽鋇囊恢稚杓啤?

下面是幾個相關於GDB語言環境的命令:

show language 檢視當前的語言環境。如果GDB不能識為你所除錯的程式語言,那麼,C語言被認為是預設的環境。 info frame 檢視當前函式的程式語言。 info source 檢視當前檔案的程式語言。 如果GDB沒有檢測出當前的程式語言,那麼你也可以手動設定當前的程式語言。使用set language命令即可做到。

當set language命令後什麼也不跟的話,你可以檢視GDB所支援的語言種類:

(gdb) set languageThe currently understood settings are:

local or auto    Automatic setting based on source filec                Use the C languagec++              Use the C++ languageasm              Use the Asm languagechill            Use the Chill languagefortran          Use the Fortran languagejava             Use the Java languagemodula-2         Use the Modula-2 languagepascal           Use the Pascal languagescheme           Use the Scheme language

於是你可以在set language後跟上被列出來的程式語言名,來設定當前的語言環境。

[編輯] 後記GDB是一個強大的命令列除錯工具。大家知道命令列的強大就是在於,其可以形成執行序列,?緯山瘧盡NIX下的軟體全是命令列的,這給程式開發提代供了極大的便利,命令列軟體的優勢在於,它?強梢苑淺H菀椎募稍諞黃穡褂眉父黽虻サ囊延洩ぞ叩拿睿塗梢宰齔鮃桓齜淺G看?的功能。

於是UNIX下的軟體比Windows下的軟體更能有機地結合,各自發揮各自的長處,組合成更為強勁的功能。而Windows下的圖形軟體基本上是各自為營,互相不能呼叫,很不利於各種軟體的相互整合。在這裡?⒉皇且蚖indows做個什麼比較,所謂“寸有所長,尺有所短”,圖形化工具還是有不如命令列的地方。(?吹秸餼浠笆保M魑磺蛟僖膊灰銜揖褪恰氨墒油夾謂緱妗保臀姨Ц芰?)

我是根據版本為5.1.1的GDB所寫的這篇文章,所以可能有些功能已被修改,或是又有更為強勁的功能。而且,我寫得?淺2執伲吹帽冉霞蚵裕⑶遙渲形乙丫吹接行磯啻肀鸌至耍ㄎ矣夢灞剩源磣秩?你看不懂),所以,我在這裡對我文中的差錯表示萬分的歉意。

文中所羅列的GDB的功能時,我只是羅列了一些帶用的GDB的命令和使用方法,其實,我這裡只講述的功能大約只佔GDB所有功能的60%吧,詳細的文件,還是請檢視GDB的幫助和使用手冊吧,或許,過段時間,如果我有空,我再寫一篇GDB的高階使用。

我個人非常喜歡GDB的自動除錯的功能,這個功能真的很強大,試想,我在UNIX下寫個指令碼,讓指令碼自動編譯我的程式,被自動除錯,並把結果報告出來,除錯成功,自?痗heckin原始碼庫。一個命令,編譯帶著除錯帶著checkin,多爽啊。只是GDB對自動化除錯目前支援還不是很成熟,只能實現半自動化,真心期望著GDB的自動化除錯功能的成熟。

如果各位對GDB或是別的技術問題有興趣的話,歡迎和我討論交流。本人目前主要在UNIX下做產品軟體的開發,所以,對UNIX下的軟體開發比較熟悉,當然,不單單是技術,對軟體工程實施,軟體設計,系統分析,?釒抗芾砦乙猜雜行牡謾;隊蠹藝椅醫渙鰨≦Q是:753640,MSN 是:[email protected].com)

[編輯] 相關詞條GCC新手入門 C/C++ IDE簡介 用GDB除錯程式 Gtk與Qt編譯環境安裝與配置 跟我一起寫Makefile  C編譯初步 C++編譯初步 Fortran編譯初步 C和C++混合編譯初步 C和Fortran混合編譯初步