天天看點

用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   <---------- 啟動GDB

GNU gdb 6.7.1-debian

Copyright (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>

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;

(gdb)    <-------------------- 直接回車表示,重複上一次指令

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;

(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    What

1   breakpoint     keep y   0x080483b2 in main at tst.c:16

2   breakpoint     keep y   0x0804837a in func at tst.c:5

(gdb) r    <--------------------- 運作程式,run指令簡寫

Starting program: /home/dbzhang/tst

Breakpoint 1, main () at tst.c:17

17  long result = 0;

(gdb) n     <--------------------- 單條語句執行,next指令簡寫。

18  for(i=1; i<=100; i++)

(gdb) n

20   result += i;

(gdb) n

18  for(i=1; i<=100; i++)

(gdb) n

20   result += i;

(gdb) c    <--------------------- 繼續運作程式,continue指令簡寫。

Continuing.

result[1-100] = 5050    <----------程式輸出。

Breakpoint 2, func (n=250) at tst.c:5

5  int sum=0,i;

(gdb) n

6  for(i=1; i<=n; i++)

(gdb) p i   <--------------------- 列印變量i的值,print指令簡寫。

$1 = -1074568236

(gdb) n

8   sum+=i;

(gdb) n

6  for(i=1; i<=n; i++)

(gdb) p sum

$2 = 1

(gdb) n

8   sum+=i;

(gdb) p i

$3 = 2

(gdb) n

6  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:6

0x080483f1 in main () at tst.c:24

24  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指令來檢視,如下所示:

$ gdb

GNU gdb 6.7.1-debian

Copyright (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) 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 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 func

Breakpoint 1 at 0x804837a: file tst.c, line 5.

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

(gdb) b

backtrace break bt

(gdb)

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

(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

[編輯] 調試已運作的程式

兩種方法:

在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>0

commands

printf "x is %d/n",x

continue

end

斷點設定在函數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 6

Breakpoint 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 unwanted

breakpoints.

(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-mode

set step-mode on

打開step-mode模式,于是,在進行單步跟蹤時,程式不會因為沒有debug

資訊而不停住。這個參數有很利于檢視機器碼。

set step-mod off

關閉step-mode模式。

finish

運作程式,直到目前函數完成傳回。并列印函數傳回時的堆棧位址和傳回值及參數值等信?

ⅰ?

until 或 u

當你厭倦了在一個循環體内單步跟蹤時,這個指令可以運作程式直到退出循環體。

stepi 或 si

nexti 或 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不會告訴你收到信号的資訊。

pass

noignore

當被調試的程式收到信号時,GDB不處理信号。這表示,GDB

會把這個信号交給被調試程式會處理。

nopass

ignore

當被調試的程式收到信号時,GDB不會讓被調試程式來處理這個信号。

info signals

info 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指令:

backtrace

bt

列印目前的函數調用棧的所有資訊。如:

(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 frame

info f

這個指令會列印出更為詳細的目前棧層的資訊,隻不過,大多數都是運作時的内内位址。?

熱纾漢刂罰饔煤牡刂罰壞饔煤牡刂罰殼暗暮怯墒裁囪某縧蛴镅?

寫成的、函數參數位址及值、局部變量的位址等等。如:

(gdb) info f

Stack level 0, frame at 0xbffff5d4:

eip = 0x804845d in func (tst.c:6); saved eip 0x8048524

called by frame at 0xbffff60c

source language c.

Arglist at 0xbffff5d4, args: n=250

Locals at 0xbffff5d4, Previous frame's sp is 0x0

Saved 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:func

Line 5 of "tst.c" starts at address 0x8048456 <func+6> and ends at 0x804845d <

func+13>.

還有一個指令(disassemble

)你可以檢視源程式的目前執行時的機器碼,這個指令會把目前記憶體中的指令dump

出來。如下面的示例表示檢視函數func的彙編代碼。

(gdb) disassemble func

Dump of assembler code for function func:

0x8048450 <func>:       push   %ebp

0x8048451 <func+1>:     mov    %esp,%ebp

0x8048453 <func+3>:     sub    $0x18,%esp

0x8048456 <func+6>:     movl   $0x0,0xfffffffc(%ebp)

0x804845d <func+13>:    movl   $0x1,0xfffffff8(%ebp)

0x8048464 <func+20>:    mov    0xfffffff8(%ebp),%eax

0x8048467 <func+23>:    cmp    0x8(%ebp),%eax

0x804846a <func+26>:    jle    0x8048470 <func+32>

0x804846c <func+28>:    jmp    0x8048480 <func+48>

0x804846e <func+30>:    mov    %esi,%esi

0x8048470 <func+32>:    mov    0xfffffff8(%ebp),%eax

0x8048473 <func+35>:    add    %eax,0xfffffffc(%ebp)

0x8048476 <func+38>:    incl   0xfffffff8(%ebp)

0x8048479 <func+41>:    jmp    0x8048464 <func+20>

0x804847b <func+43>:    nop

0x804847c <func+44>:    lea    0x0(%esi,1),%esi

0x8048480 <func+48>:    mov    0xfffffffc(%ebp),%edx

0x8048483 <func+51>:    mov    %edx,%eax

0x8048485 <func+53>:    jmp    0x8048487 <func+55>

0x8048487 <func+55>:    mov    %ebp,%esp

0x8048489 <func+57>:    pop    %ebp

0x804848a <func+58>:    ret

End 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::variable

function::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調試過程中,你可以以如下指令顯示出這個動态數組的取值:

p *[email protected]

@的左邊是數組的首位址的值,也就是變量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 address

set print address on

打開位址輸出,當程式顯示函數資訊時,GDB

會顯出函數的參數位址。系統預設為打開的,如:

(gdb) f

#0  set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>")

    at input.c:530

530         if (lquote != def_lquote)

set print address off

關閉函數的參數位址顯示,如:

(gdb) set print addr off

(gdb) f

#0  set_quotes (lq="<<", rq=">>") at input.c:530

530         if (lquote != def_lquote)

show print address

檢視目前位址顯示選項是否打開。

set print array

set print array on

打開數組顯示,打開後當數組顯示時,每個元素占一行,如果不打開的話,每個元素則以?

漢歐指簟U飧鲅∠钅鮮槍乇盞摹S胫喙氐牧礁雒钊缦攏揖筒輝俣嗨盜恕?

set print array off

show print array

set 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 = 0

print 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 width

type = double

(gdb) p width

$4 = 13

(gdb) set width=47

Invalid 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

指令強制函數忽略還沒有執行的語句并傳回。

return

return <expression>

   使用return指令取消目前函數的執行,并立即傳回,如果指定了<expression

>,那麼該表達式的值會被認作函數的傳回值。

[編輯] 強制調用函數

call <expr>

表達式中可以一是函數,以此達到強制調用函數的目的。并顯示函數的傳回值,如果函數?

禱刂凳莢oid,那麼就不顯示。

另一個相似的指令也可以完成這一功能——print,print

後面可以跟表達式,是以也可以用他來調用函數,print和call的不同是,如果函數傳回

void,call則不顯示,print則顯示函數傳回值,并把該值存入曆史資料中。

[編輯] 在不同語言中使用GDB

GDB支援下列語言: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 language

The currently understood settings are:

local or auto    Automatic setting based on source file

c                Use the C language

c++              Use the C++ language

asm              Use the Asm language

chill            Use the Chill language

fortran          Use the Fortran language

java             Use the Java language

modula-2         Use the Modula-2 language

pascal           Use the Pascal language

scheme           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混合編譯初步

取自"http://wiki.ubuntu.org.cn/index.php?title=%E7%94%A8GDB%E8%B0%83%E8%AF%95%

E7%A8%8B%E5%BA%8F&variant=zh-cn"

1個分類: 程式開發

本文轉自

http://wiki.ubuntu.org.cn/index.php?title=%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8

%8B%E5%BA%8F&variant=zh-cn