GDB使用技巧 4 檢視執行資料

2021-10-04 14:54:19 字數 4877 閱讀 2658

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

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

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

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

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

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

指定乙個在檔案或是乙個函式中的變數。

表示乙個指向記憶體位址的型別為type的乙個物件。

在gdb中,你可以隨時檢視以下三種變數的值:

1、全域性變數(所有檔案可見的)

2、靜態全域性變數(當前檔案可見的)

3、區域性變數(當前scope可見的)

如果你的區域性變數和全域性變數發生衝突(也就是重名),一般情況下是區域性變數會隱藏全域性變數,也就是說,如果乙個全域性變數和乙個函式中的區域性變數同名時,如果當前停止點在函式中,用print顯示出的變數的值會是函式中的區域性變數的值。如果此時你想檢視全域性變數的值時,你可以使用「::」操作符:

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

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

另外,需要注意的是,如果你的程式編譯時開啟了優化選項,那麼在用gdb除錯被優化過的程式時,可能會發生某些變數不能訪問,或是取值錯誤碼的情況。這個是很正常的,因為優化程式會刪改你的程式,整理你程式的語句順序,剔除一些無意義的變數等,所以在gdb除錯這種程式時,執行時的指令和你所編寫指令就有不一樣,也就會出現你所想象不到的結果。對付這種情況時,需要在編譯程式時關閉編譯優化。一般來說,幾乎所有的編譯器都支援編譯優化的開關,例如,gnu的c/c++編譯器gcc,你可以使用「-gstabs」選項來解決這個問題。關於編譯器的引數,還請檢視編譯器的使用說明文件。

有時候,你需要檢視一段連續的記憶體空間的值。比如陣列的一段,或是動態分配的資料的大小。你可以使用gdb的「@」操作符,「@」的左邊是第乙個記憶體的位址的值,「@」的右邊則你你想檢視記憶體的長度。例如,你的程式中有這樣的語句:

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

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

一般來說,gdb會根據變數的型別輸出變數的值。但你也可以自定義gdb的輸出的格式。例如,你想輸出乙個整數的十六進製制,或是二進位制來檢視這個整型變數的中的位的情況。要做到這樣,你可以使用gdb的資料顯示格式:

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

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

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

你可以設定一些自動顯示的變數,當程式停住時,或是在你單步跟蹤時,這些變數會自動顯示。相關的gdb命令是display。

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

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

$pc是gdb的環境變數,表示著指令的位址,/i則表示輸出格式為機器指令碼,也就是彙編。於是當程式停下後,就會出現源**和機器指令碼相對應的情形,這是乙個很有意思的功能。

undisplay

delete display

刪除自動顯示,dnums意為所設定好了的自動顯式的編號。如果要同時刪除幾個,編號可以用空格分隔,如果要刪除乙個範圍內的編號,可以用減號表示(如:2-5)

disable display

enable display

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

info display

檢視display設定的自動顯示的資訊。gdb會打出一張**,向你報告當然除錯中設定了多少個自動顯示設定,其中包括,設定的編號,表示式,是否enable。

gdb中關於顯示的選項比較多,這裡我只例舉大多數常用的選項。

開啟位址輸出,當程式顯示函式資訊時,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)

檢視當前位址顯示選項是否開啟。

開啟陣列顯示,開啟後當陣列顯示時,每個元素佔一行,如果不開啟的話,每個元素則以逗號分隔。這個選項預設是關閉的。與之相關的兩個命令如下,我就不再多說了。

這個選項主要是設定陣列的,如果你的陣列太大了,那麼就可以指定乙個來指定資料顯示的最大長度,當到達這個長度時,gdb就不再往下顯示了。如果設定為0,則表示不限制。

檢視print elements的選項資訊。

如果開啟了這個選項,那麼當顯示字串時,遇到結束符則停止顯示。這個選項預設為off。

如果開啟printf pretty這個選項,那麼當gdb顯示結構體時會比較漂亮。如:

$1 = ,

meat = 0x54 "pork"

}關閉printf pretty這個選項,gdb顯示結構體時會如下顯示:

$1 = , meat = 0x54 "pork"}

檢視gdb是如何顯示結構體的。

設定字元顯示,是否按「/nnn」的格式顯示,如果開啟,則字串或字元資料按/nnn顯示,如「/065」。

檢視字元顯示開關是否開啟。

設定顯示結構體時,是否顯式其內的聯合體資料。例如有以下資料結構:

typedef enum species;

typedef enum tree_forms;

typedef enum

bug_forms;

struct thing form;

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

$1 = }

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

$1 = }

檢視聯合體資料的顯示方式

在c++中,如果乙個物件指標指向其派生類,如果開啟這個選項,gdb會自動按照虛方法呼叫的規則顯示輸出,如果關閉這個選項的話,gdb就不管虛函式表了。這個選項預設是off。

檢視物件選項的設定。

這個選項表示,當顯示乙個c++物件中的內容是,是否顯示其中的靜態資料成員。預設是on。

檢視靜態資料成員選項設定。

當此選項開啟時,gdb將用比較規整的格式來顯示虛函式表時。其預設是關閉的。

檢視虛函式顯示格式的選項。

當你用gdb的print檢視程式執行時的資料時,你每乙個print都會被gdb記錄下來。gdb會以$1, $2, $3 .....這樣的方式為你每乙個print命令編上號。於是,你可以使用這個編號訪問以前的表示式,如$1。這個功能所帶來的好處是,如果你先前輸入了乙個比較長的表示式,如果你還想檢視這個表示式的值,你可以使用歷史記錄來訪問,省去了重複輸入。

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

使用環境變數時,gdb會在你第一次使用時建立這個變數,而在以後的使用中,則直接對其賦值。環境變數沒有型別,你可以給環境變數定義任一的型別。包括結構體和陣列。

該命令檢視當前所設定的所有的環境變數。

這是乙個比較強大的功能,環境變數和程式變數的互動使用,將使得程式除錯更為靈活便捷。例如:

於是,當你就不必,print bar[0]->contents, print bar[1]->contents地輸入命令了。輸入這樣的命令後,只用敲回車,重複執行上一條語句,環境變數會自動累加,從而完成逐個輸出的功能。

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

檢視暫存器的情況。(除了浮點暫存器)

檢視所有暫存器的情況。(包括浮點暫存器)

檢視所指定的暫存器的情況。

暫存器中放置了程式執行時的資料,比如程式當前執行的指令位址(ip),程式的當前堆疊位址(sp)等等。你同樣可以使用print命令來訪問暫存器的情況,只需要在暫存器名字前加乙個$符號就可以了。如:p $eip。

用GDB除錯程式 檢視執行時資料

參考自 http hi.baidu.com wg wang blog item dad263c2f5598630e5dd3ba6.html 在使用gdb除錯程式時,觸發斷點後,可以使用 print 命令 簡寫為 p 或是同義命令 inspect 來檢視當前程式的執行資料。print 命令的格式是 p...

使用儲存過程執行資料庫備份

create proc bakup database as declare strpsw varchar 50 declare strusr varchar 50 declare strcmdshell varchar 300 declare strdatabasename varchar 20 d...

用GDB除錯程式 10 檢視執行時資料(1)

用gdb除錯程式 10 檢視執行時資料 1 在你除錯程式時,當程式被停住時,你可以使用print命令 簡寫命令為p 或是同義命令inspect來檢視當前程式的執行資料。print命令的格式是 print print 是表示式,是你所除錯的程式的語言的表示式 gdb可以除錯多種程式語言 是輸出的格式,...