首頁>技術>

GDB簡介

GDB(GNU Debugger)是一個強大的命令列除錯工具。一般的,在Windows下進行開發,很少操控命令列除錯,偵錯程式大多與編譯器都整合在IDE裡了。當然在Windows下也可以直接使用gcc、gdb來做編譯除錯我們的C程式,如MinGW( 一個可自由使用和自由釋出的Windows特定標頭檔案和使用GNU工具集匯入庫的集合 )中就同時包含有gcc與gdb工具:

使用gdb -v命令可檢視gdb的版本:

示例程式碼gdb_test.c:

一般的,我們使用如下命令來編譯:

gcc gdb_test.c -o gdb_test.exe

這樣編譯出來的gdb_test.exe是不帶除錯資訊的。我們必須編譯出帶有除錯資訊(如行號等資訊)的可執行檔案才能使用gdb進行除錯。在以上基礎上加個-g引數即可生成除錯資訊。

除此之外,我們編譯時應不使用最佳化選項,若使用最佳化,則編譯器會對程式進行一些最佳化,有可能會更改語句的順序及最佳化一些變數,從而可能會導致程式執行流程與原始碼流程不匹配的情況。進一步,可以使用-Wall引數開啟所有警告,所以我們的編譯命令變為:

gcc -g -Wall gdb_test.c -o gdb_test.exe
1、GDB常用命令

下面粗略地列出一些常用的命令:

2、demo除錯分析

使用上面的編譯命令編譯得到帶除錯資訊的可執行程式gdb_test.exe,有兩種方法啟動除錯。

一種方法是先輸入gdb命令進入gdb環境,再輸入file+可執行程式裝入除錯檔案,即:

另一種方法是直接輸入gdb+可執行程式對該程式進行除錯,即:

(1)除錯測試函式1

上面的測試函式1大家思考得出結果了嗎?我們單步除錯看看結果是怎麼樣的:

① 在test1函式入口打個斷點:② 執行到斷點處:③ 單步往下執行:

顯然,單步執行到了這一句我們就得出了測試函式1的結果,即輸出 i = 1。大家分析得對了嗎?這要是不注意還真的容易出錯,這裡的if判斷條件裡用的是=號,而不是==號,這個小陷阱可能會迷惑一些初學C語言的朋友。

if語句的通用形式為:

if (expression)    statement

可以明確的是:如果對expression為真(非0),則執行statement。本題中,如if (i = 0)其實就等價於

i = 0;if (i)

顯然這裡的if語句的expression為假,不會執行statement。

類似的if (i = 1)等價於

i = 1;if (i)

顯然這裡的if語句的expression為真,執行statement。

平時在發現自己寫的程式碼執行的流程異常時,不妨debug除錯一下,一步一步地走,看程式是否按照自己設計的流程走,看是不是我們的執行邏輯設計錯了。

(2)除錯測試函式2

測試函式2也是一道極其經典的面試題目。不能一眼看出結果?沒關係,我們一起除錯分析一下。接著上面的流程,我們輸出quit命令推出gdb環境,再重新進入除錯test2。

① 在test2函式入口打個斷點:② 執行到斷點處:

此時,我們不妨看一下a[1]元素的地址及a數組裡面的內容是什麼:

可見,在陣列初始化之前,整個陣列空間裡的值是一些隨機值。這裡反映一個問題,區域性變數在初始化之前的值是無規律的,所以不妨在定義區域性變數的時候初始化一個確定的值,防止出錯。

因為此時第23行這條語句還未執行,所以p指向的地址還不是a[1]元素的地址。

再單步往下執行,然後我們看一下,指標變數p的值,及以指標變數p的值為首地址、往後偏移10個記憶體單元為結束地址,這一段空間內的值是什麼:

至此,我們透過除錯清晰地得到了p[6]的值。

繼續單步往下執行,我們看一下,&a[0]的值、&a的值、(&a+1)的值、p1的值:

從gdb輸出的資訊我們知道&a的型別是(int (*) [10] ),即是一個指向含有10個元素的整形陣列的指標,所以(&a+1)的意義是往後偏移10 * sizeof(int)。進一步,再利用一下其它輸出的資訊:

&a的值為0x61fee0&a+1的值為0x61ff08

兩個值相減得到40,正好是整個陣列所佔的位元組數。

而p1是一個整形指標,所以p1-1指向的就是往前偏移sizeof(int)個位元組的地址,即a[9]的地址(0x61ff04),所以*(p1 - 1)的值也就是a[9]的值。最後我們再看一下&a往後的40個地址裡的值都是些什麼:

以上就是本次的例項演示,只是用到了一小部分gdb的命令,還有更多命令大家可以自己練習使用,基本的會了,不懂的地方遇到的時候再查也來得及。

30
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 欄位修改記錄操作日誌的實現