摘 要:本文通過對linux下調(diào)試工具gdb工作原理的研究,結(jié)合gdb常用命令,設(shè)置斷點、查看變量、改變程序執(zhí)行方式,運用gdb調(diào)試并修改程序,達到了程序調(diào)試的目標。
關(guān)鍵詞:gdb調(diào)試;斷點;變量;流程
中圖分類號:TP316.81 文獻標識碼:A 文章編號:1674-7712 (2014) 22-0000-02
隨著Linux的興起,越來越多的人在Linux下開發(fā)程序,對于用慣了IDE開發(fā)工具的那些人來說,會覺得還是Windows下的IED工具不錯。其實,gdb是GNU組織的調(diào)試器,也是Linux環(huán)境下進程程序除錯的常用工具。調(diào)試是將編制的程序在正式投入實際運行之前,運用手工或編譯程序等方法進行測試,對程序中的語法錯誤和邏輯錯誤進行修正的過程。為了保證計算機信息系統(tǒng)運行的正確性,調(diào)試是編程中必不可少的環(huán)節(jié)。本文詳細研究了gdb調(diào)試的工作原理,并演示其調(diào)試過程。
一、準備
(一)使用vim編輯接口文件mysum.h代碼
(二)使用gcc編譯
加上-o參數(shù)指定生成的可執(zhí)行文件名testsum,默認為a.out;加上-g參數(shù),生成可調(diào)試的執(zhí)行文件testsum,此執(zhí)行文件中含有調(diào)試信息,如果調(diào)試不包含提示信息的目標代碼,程序中的函數(shù)名、變量名全部使用運行時的內(nèi)存地址表示,查看和調(diào)試都不方便。命令如下:
gcc-g-o testsum testsum.c mysum.c或者:
gcc testsum.c mysum.c-g-otestsum
完成以上的準備工作,剩下的就該gdb出馬了。使用gdb調(diào)試:
gdb testsum(可執(zhí)行文件名),顯示有關(guān)gdb的版權(quán)與配置信息,出現(xiàn)(gdb)提示符,說明gdb已經(jīng)準備好了,接收命令輸入。其實gdb除了可以調(diào)試可執(zhí)行程序外,也可以調(diào)試程序運行非正常退出產(chǎn)生的core文件,甚至可以通過進程PID,進行遠程調(diào)試。
二、使用gdb暫停程序的執(zhí)行
(一)使用命令break(可以簡寫為b)條件設(shè)置斷點
b 12 表示在程序代碼的第12行設(shè)置斷點;
b functionname 表示在函數(shù)的入口處設(shè)置斷點;
b 0x40057a 表示在地址40057a處設(shè)置斷點;
b functionname if argument==100 表示當functionname函數(shù)中的變量argument為100時,程序?qū)嵤┲袛啵?/p>
(二)使用命令watch根據(jù)表達式的值暫停程序
watch變量(表達式)表示當變量的值或表達式發(fā)生變化時,暫停程序執(zhí)行;
rwatch變量(表達式)表示當讀取到變量的值或表達式時,暫停程序執(zhí)行;
awatch變量(表達式)表示當讀寫變量的值或表達式時,暫停程序執(zhí)行;
(三)使用命令handle根據(jù)捕捉到的信號與設(shè)置的參數(shù)不同,影響gdb的處理結(jié)果
基本命令格式:handle argu signals,其中argu的可能取值:
stop:表示收到信號后,暫停程序
nostop:表示收到信號后,不暫停程序,出現(xiàn)信號的信息
print:表示收到信號后,顯示信號信息
noprint:表示收到信號后,不顯示信號信息
pass or noignore:表示gdb把信號交給被調(diào)試的程序處理
nopass or ignore:表示gdb不把信號交給被調(diào)試的程序處理
三、使用gdb查看程序的運行數(shù)據(jù)
(一)print命令(可以簡寫為p)查看變量信息
p /format variablename:表示查看variablename變量的內(nèi)容,其中/format可以使用表1中的參數(shù)替換,對應含義見前。
例:p i查看i變量的值,默認是十進制格式查看變量的內(nèi)容,結(jié)果為$2=17
p /d i查看i變量十進制格式的內(nèi)容,結(jié)果為 $3=17
p /x i 查看i變量十六進制格式的內(nèi)容,結(jié)果為$4=0x11
p /t i 查看i變量二進制格式的內(nèi)容,結(jié)果為 $4=10001
(二)examine(可以簡寫為x)命令查看內(nèi)存信息
examine /n format u + 內(nèi)存地址(指針變量):表示查看指定內(nèi)存地址或指針變量的內(nèi)容,/n表示顯示內(nèi)存長度, format的格式含義見表1,u表示以特定字節(jié)數(shù)表示,默認是四個字節(jié),b、h、w、g分別表示單字節(jié)、雙字節(jié)、四字節(jié)和八個字節(jié),顯示情況與最近一次顯示變量的表示方式有關(guān)。
(三)backtrace(可以簡寫為bt)命令查看棧內(nèi)信息
backtrace [n]:表示查看棧頂上n層棧信息;backtrace [-n]:表示查看棧底上n層棧信息;backtrace:只用命令表示打印所有棧信息。
例:#0 main (argc=1, argv=0x7fffffffe538) at testsum.c:9
四、具體使用gdb調(diào)試程序
由于本程序中,一方面通過函數(shù)mysum通過傳入?yún)?shù)的形式mysum(1,100)的方式計算1-100的和,另一方面通過main函數(shù)中的自己實現(xiàn)求1-100的和,很明顯發(fā)現(xiàn)結(jié)果是函數(shù)mysum的運行結(jié)果不對。在編譯過程中通過加入?yún)?shù)-g實現(xiàn)可執(zhí)行文件包含調(diào)試信息。
首先:使用gdb testsum命令后,進入到gdb調(diào)試環(huán)境,必要的提示信息后,直到“(gdb)”提示符出現(xiàn)后,表明gdb已經(jīng)做好了交互調(diào)試的準備。
接著:查看源碼信息,設(shè)置斷點,b main;b mysum;b 11;b 12;分別在main函數(shù)、mysum函數(shù)、第11行、第12行設(shè)置了斷點,i b命令查看斷點信息,確認斷點信息。
然后:使用r命令運行程序,程序在第一個斷點即main方法處停下,使用n命令執(zhí)行下一條指令,再次使用n,當?shù)谌问褂胣命令,就會發(fā)現(xiàn)指令的執(zhí)行一直在第8行和第9行之間跳轉(zhuǎn),for循環(huán)的執(zhí)行就是不停的判斷條件,并執(zhí)行指令。使用c命令,全部執(zhí)行完for循環(huán),p i查看i的變量為101,p result結(jié)果為5050,結(jié)果正確。
最后:使用命令n進入下一語句,使用s命令步入mysum函數(shù)內(nèi)部,可以多次使用n命令觀察程序的執(zhí)行流程,使用b mysum if i=98,設(shè)置條件斷點,當i=98時,程序暫停,使用n執(zhí)行語句,最后查看mysum函數(shù)退出前i=100,發(fā)現(xiàn)是for的退出條件設(shè)置問題,修改為for(i=m;i<=n;i++)問題解決。
總結(jié)整個調(diào)試過程,gdb調(diào)試和其他調(diào)試工具都是一樣的功能。主要通過以下步驟完成調(diào)試:
(1)編譯代碼,加入調(diào)試信息。
(2)啟動gdb調(diào)試環(huán)境,設(shè)置斷點,根據(jù)須要在斷點處暫停程序。
(3)查看暫停程序中變量的內(nèi)容,函數(shù)的棧、指針等內(nèi)容。
(4)改變程序的運行方式,單步執(zhí)行程序,查看程序的執(zhí)行流程。
經(jīng)過以上步驟,發(fā)現(xiàn)問題所在,修改代碼,改正錯誤。gdb調(diào)試工具雖說是基于命令行的調(diào)試工具,卻比VC等圖形化調(diào)試工具更為強大。gdb也可以調(diào)試程序非正常退出時生成的core文件,甚至在服務器端正在運行的程序,通過制定進程pid,使用gdb進行遠程調(diào)試,這也許是gdb一直經(jīng)久不衰的原因吧!
參考文獻:
[1]Frank M.Carrano Timothy Henry.景麗,譯.C++數(shù)據(jù)抽象和問題求解(第6版)[M].北京:清華大學出版社,2013.
[2]Eric S.Roberts.閃四清,譯.C程序設(shè)計的抽象思維[M].北京:機械工業(yè)出版社,2012.
[作者簡介]郭書超(1977-),男,講師,碩士,研究方向:軟件開發(fā)。