The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks
          Gdb 調(diào)試器
          調(diào)試是所有程序員都會面臨的問題。如何提高程序員的調(diào)試效率,更好更快地定位程序中的問題從而加快程序開發(fā)的進度,是大家共同面對的。就如讀者熟知的Windows下的一些調(diào)試工具,如VC自帶的如設(shè)置斷點、單步跟蹤等,都受到了廣大用戶的贊賞。那么,在Linux下有什么很好的調(diào)試工具呢?
          本文所介紹的Gdb 調(diào)試器是一款GNU 開發(fā)組織并發(fā)布的UNIX/Linux 下的程序調(diào)試工具。雖然,它沒有圖形化的友好界面,但是它強大的功能也足以與微軟的VC 工具等媲美。
          下面就請跟隨筆者一步步學(xué)習(xí)Gdb調(diào)試器。
          3.5.1 Gdb使用流程
          這里給出了一個短小的程序,由此帶領(lǐng)讀者熟悉一下Gdb 的使用流程。建議讀者能夠?qū)?/div>
          際動手操作。
          首先,打開Linux 下的編輯器Vi或者Emacs,編輯如下代碼(由于為了更好地熟悉Gdb的操作,筆者在此使用Vi 編輯,希望讀者能夠參見3.3 節(jié)中對Vi 的介紹,并熟練使用Vi)。
          /*test.c*/
          #include <stdio.h>
          int sum(int m);
          int main()
          {
          int i,n=0;
          sum(50);
          for(i=1; i<=50; i++)
          {
          n += i;
          }
          printf("The sum of 1-50 is %d \n", n );
          }
          int sum(int m)
          {
          int i,n=0;
          for(i=1; i<=m;i++)
          n += i;
          printf("The sum of 1-m is %d\n", n);
          }
          在保存退出后首先使用Gcc對test.c進行編譯,注意一定要加上選項“-g”,這樣編譯出的可執(zhí)行代碼中才包含調(diào)試信息,否則之后Gdb 無法載入該可執(zhí)行文件。
          [root@localhost Gdb]# gcc -g test.c -o test
          雖然這段程序沒有錯誤,但調(diào)試完全正確的程序可以更加了解Gdb 的使用流程。接下來就啟動Gdb 進行調(diào)試。注意,Gdb 進行調(diào)試的是可執(zhí)行文件,而不是如“.c”的源代碼,因此,需要先通過Gcc編譯生成可執(zhí)行文件才能用Gdb進行調(diào)試。
          [root@localhost Gdb]# gdb test
          GNU Gdb Red Hat Linux (6.3.0.0-1.21rh)
          Copyright 2004 Free Software Foundation, Inc.
          GDB is free software, covered by the GNU General Public License, and you are
          welcome to change it and/or distribute copies of it under certain conditions.
          Type "show copying" to see the conditions.
          There is absolutely no warranty for GDB. Type "show warranty" for details.
          This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db
          library "/lib/libthread_db.so.1".
          (gdb)
          可以看出,在Gdb 的啟動畫面中指出了Gdb 的版本號、使用的庫文件等信息,接下來就進入了由“(gdb)”開頭的命令行界面了。
          (1)查看文件
          在 Gdb 中鍵入“l”(list)就可以查看所載入的文件,如下所示:
          注意
          在Gdb的命令中都可使用縮略形式的命令,如“l”代便“list”,“b”代表“breakpoint”,“p”代表“print”等,讀者也可使用“help”命令查看幫助信息。
          (Gdb) l
          1 #include <stdio.h>
          2 int sum(int m);
          3 int main()
          4 {
          5 int i,n=0;
          6 sum(50);
          7 for(i=1; i<=50; i++)
          8 {
          9 n += i;
          10 }
          (Gdb) l
          11 printf("The sum of 1~50 is %d \n", n );
          12
          13 }
          14 int sum(int m)
          15 {
          16 int i,n=0;
          17 for(i=1; i<=m;i++)
          18 n += i;
          19 printf("The sum of 1~m is = %d\n", n);
          20 }
          可以看出,Gdb 列出的源代碼中明確地給出了對應(yīng)的行號,這樣就可以大大地方便代碼的定位。
          (2)設(shè)置斷點
          設(shè)置斷點是調(diào)試程序中是一個非常重要的手段,它可以使程序到一定位置暫停它的運行。因此,程序員在該位置處可以方便地查看變量的值、堆棧情況等,從而找出代碼的癥結(jié)所在。
          在 Gdb 中設(shè)置斷點非常簡單,只需在“b”后加入對應(yīng)的行號即可(這是最常用的方式,另外還有其他方式設(shè)置斷點)。如下所示:
          (Gdb) b 6
          Breakpoint 1 at 0x804846d: file test.c, line 6.
          要注意的是,在Gdb 中利用行號設(shè)置斷點是指代碼運行到對應(yīng)行之前將其停止,如上例中,代碼運行到第5行之前暫停(并沒有運行第5行)。
          (3)查看斷點情況
          在設(shè)置完斷點之后,用戶可以鍵入“info b”來查看設(shè)置斷點情況,在Gdb 中可以設(shè)置
          多個斷點。
          (Gdb) info b
          Num Type Disp Enb Address What
          1 breakpoint keep y 0x0804846d in main at test.c:6
          (4)運行代碼
          接下來就可運行代碼了,Gdb默認(rèn)從首行開始運行代碼,可鍵入“r”(run)即可(若想從程序中指定行開始運行,可在r 后面加上行號)。
          (Gdb) r
          Starting program: /root/workplace/Gdb/test
          Reading symbols from shared object read from target memory...done.
          Loaded system supplied DSO at 0x5fb000
          Breakpoint 1, main () at test.c:6
          6 sum(50);
          可以看到,程序運行到斷點處就停止了。
          (5)查看變量值
          在程序停止運行之后,程序員所要做的工作是查看斷點處的相關(guān)變量值。在Gdb 中只需
          鍵入“p”+變量值即可,如下所示:
          (Gdb) p n
          $1 = 0
          (Gdb) p i
          $2 = 134518440
          在此處,為什么變量“i”的值為如此奇怪的一個數(shù)字呢?原因就在于程序是在斷點設(shè)置的對應(yīng)行之前停止的,那么在此時,并沒有把“i”的數(shù)值賦為零,而只是一個隨機的數(shù)字。但變量“n”是在第四行賦值的,故在此時已經(jīng)為零。
          小技巧
          Gdb 在顯示變量值時都會在對應(yīng)值之前加上“$N”標(biāo)記,它是當(dāng)前變量值的引用標(biāo)記,所以以后若想再次引用此變量就可以直接寫作“$N”,而無需寫冗長的變量名。
          (6)單步運行
          單步運行可以使用命令“n”(next)或“s”(step),它們之間的區(qū)別在于:若有函數(shù)調(diào)用的時候,“s”會進入該函數(shù)而“n”不會進入該函數(shù)。因此,“s”就類似于VC等工具中的
          “step in”,“n”類似與VC等工具中的“step over”。它們的使用如下所示:
          (Gdb) n
          The sum of 1-m is 1275
          7 for(i=1; i<=50; i++)
          (Gdb) s
          sum (m=50) at test.c:16
          16 int i,n=0;
          可見,使用“n”后,程序顯示函數(shù)sum的運行結(jié)果并向下執(zhí)行,而使用“s”后則進入到sum函數(shù)之中單步運行。
          (7)恢復(fù)程序運行
          在查看完所需變量及堆棧情況后,就可以使用命令“c”(continue)恢復(fù)程序的正常運行了。這時,它會把剩余還未執(zhí)行的程序執(zhí)行完,并顯示剩余程序中的執(zhí)行結(jié)果。以下是之前使用“n”命令恢復(fù)后的執(zhí)行結(jié)果:
          (Gdb) c
          Continuing.
          The sum of 1-50 is :1275
          Program exited with code 031.
          可以看出,程序在運行完后退出,之后程序處于“停止?fàn)顟B(tài)”。
          小知識
          在Gdb中,程序的運行狀態(tài)有“運行”、“暫停”和“停止”3種,其中“暫停”狀態(tài)為程序遇到了斷點或觀察點之類的,程序暫時停止運行,而此時函數(shù)的地址、函數(shù)參數(shù)、函數(shù)內(nèi)的局部變量都會被壓入“棧”(Stack)中。故在這種狀態(tài)下可以查看函數(shù)的變量值等各種屬性。但在函數(shù)處于“停止”狀態(tài)之后,“棧”就會自動撤銷,它也就無法查看各種信息了。
          3.5.2 Gdb基本命令
          Gdb 的命令可以通過查看help 進行查找,由于Gdb 的命令很多,因此Gdb 的help 將其分成了很多種類(class),用戶可以通過進一步查看相關(guān)class找到相應(yīng)命令。如下所示:
          (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
          Type "help" followed by a class name for a list of commands in that class.
          Type "help" followed by command name for full documentation.
          Command name abbreViations are allowed if unambiguous.
          上述列出了Gdb 各個分類的命令,注意底部的加粗部分說明其為分類命令。接下來可以
          具體查找各分類種的命令。如下所示:
          (gdb) help data
          Examining data.
          List of commands:
          call -- Call a function in the program
          delete display -- Cancel some expressions to be displayed when program stops
          delete mem -- Delete memory region
          disable display -- Disable some expressions to be displayed when program stops
          Type "help" followed by command name for full documentation.
          Command name abbreViations are allowed if unambiguous.
          至此,若用戶想要查找call命令,就可鍵入“help call”。
          (gdb) help call
          Call a function in the program.
          The argument is the function name and arguments, in the notation of the
          current working language. The result is printed and saved in the value
          history, if it is not void.
          當(dāng)然,若用戶已知命令名,直接鍵入“help [command]”也是可以的。
          Gdb 中的命令主要分為以下幾類:工作環(huán)境相關(guān)命令、設(shè)置斷點與恢復(fù)命令、源代碼查看命令、查看運行數(shù)據(jù)相關(guān)命令及修改運行參數(shù)命令。以下就分別對這幾類的命令進行講解。
          1.工作環(huán)境相關(guān)命令
          Gdb中不僅可以調(diào)試所運行的程序,而且還可以對程序相關(guān)的工作環(huán)境進行相應(yīng)的設(shè)定,甚至還可以使用shell 中的命令進行相關(guān)的操作,其功能極其強大。表3.10 所示為Gdb 常見工作環(huán)境相關(guān)命令。
          表3.10 Gdb 工作環(huán)境相關(guān)命令
          命令格式 含義
          set args 運行時的參數(shù)指定運行時參數(shù),如set args 2
          show args 查看設(shè)置好的運行參數(shù)
          path dir 設(shè)定程序的運行路徑
          show paths 查看程序的運行路徑
          set enVironment var [=value] 設(shè)置環(huán)境變量
          show enVironment [var] 查看環(huán)境變量
          cd dir 進入到dir目錄,相當(dāng)于shell中的cd命令
          pwd 顯示當(dāng)前工作目錄
          shell command 運行shell的command命令
          2.設(shè)置斷點與恢復(fù)命令
          Gdb 中設(shè)置斷點與恢復(fù)的常見命令如表3.11 所示。
          表 3.11 Gdb 設(shè)置斷點與恢復(fù)相關(guān)命令
          命令格式  含義
          bnfo b 查看所設(shè)斷點
          break 行號或函數(shù)名 <條件表達(dá)式> 設(shè)置斷點
          tbreak 行號或函數(shù)名 <條件表達(dá)式> 設(shè)置臨時斷點,到達(dá)后被自動刪除
          delete [斷點號] 刪除指定斷點,其斷點號為“info b”中的第一欄。若缺省斷點號則刪除所有斷點
          disable [斷點號]] 停止指定斷點,使用“info b”仍能查看此斷點。同delete一樣,省斷點號則停止所有斷點
          enable  [斷點號] 激活指定斷點,即激活被disable停止的斷點
          condition [斷點號] <條件表達(dá)式> 修改對應(yīng)斷點的條件
          ignore [斷點號]<num> 在程序執(zhí)行中,忽略對應(yīng)斷點num次
          step 單步恢復(fù)程序運行,且進入函數(shù)調(diào)用
          next 單步恢復(fù)程序運行,但不進入函數(shù)調(diào)用
          finish 運行程序,直到當(dāng)前函數(shù)完成返回
          c 繼續(xù)執(zhí)行函數(shù),直到函數(shù)結(jié)束或遇到新的斷點
          由于設(shè)置斷點在Gdb 的調(diào)試中非常重要,所以在此再著重講解一下Gdb中設(shè)置斷點的方法。Gdb 中設(shè)置斷點有多種方式:其一是按行設(shè)置斷點,設(shè)置方法在3.5.1節(jié)已經(jīng)指出,在此就不重復(fù)了。另外還可以設(shè)置函數(shù)斷點和條件斷點,在此結(jié)合上一小節(jié)的代碼,具體介紹后兩種設(shè)置斷點的方法。
          ① 函數(shù)斷點
          Gdb 中按函數(shù)設(shè)置斷點只需把函數(shù)名列在命令“b”之后,如下所示:
          (gdb) b sum
          Breakpoint 1 at 0x80484ba: file test.c, line 16.
          (gdb) info b
          Num Type Disp Enb Address What
          1 breakpoint keep y 0x080484ba in sum at test.c:16
          要注意的是,此時的斷點實際是在函數(shù)的定義處,也就是在16 行處(注意第16 行還未
          執(zhí)行)。
          ② 條件斷點
          Gdb 中設(shè)置條件斷點的格式為:b 行數(shù)或函數(shù)名if 表達(dá)式。具體實例如下所示:
          (gdb) b 8 if i==10
          Breakpoint 1 at 0x804848c: file test.c, line 8.
          (gdb) info b
          Num Type Disp Enb Address What
          1 breakpoint keep y 0x0804848c in main at test.c:8
          stop only if i == 10
          (gdb) r
          Starting program: /home/yul/test
          The sum of 1-m is 1275
          Breakpoint 1, main () at test.c:9
          9 n += i;
          (gdb) p i
          $1 = 10
          可以看到,該例中在第8 行(也就是運行完第7 行的for 循環(huán))設(shè)置了一個“i==0”的條件斷點,在程序運行之后可以看出,程序確實在i為10 時暫停運行。
          3.Gdb 中源碼查看相關(guān)命令
          在 Gdb 中可以查看源碼以方便其他操作,它的常見相關(guān)命令如表3.12 所示。
          表3.12 Gdb 源碼查看相關(guān)相關(guān)命令
          命令格式 含義
          list <行號>|<函數(shù)名> 查看指定位置代碼
          file [文件名] 加載指定文件
          forward-search  正則表達(dá)式源代碼前向搜索
          reverse-search  正則表達(dá)式源代碼后向搜索
          dir dir 停止路徑名
          show directories 顯示定義了的源文件搜索路徑
          info line 顯示加載到Gdb內(nèi)存中的代碼
          4.Gdb 中查看運行數(shù)據(jù)相關(guān)命令
          Gdb 中查看運行數(shù)據(jù)是指當(dāng)程序處于“運行”或“暫停”狀態(tài)時,可以查看的變量及表
          達(dá)式的信息,其常見命令如表3.13 所示:
          表3.13 Gdb 查看運行數(shù)據(jù)相關(guān)命令
          命令格式 含義
          print 表達(dá)式|變量查看程序運行時對應(yīng)表達(dá)式和變量的值
          x <n/f/u>   查看內(nèi)存變量內(nèi)容。其中n為整數(shù)表示顯示內(nèi)存的長度,f表示顯示的格式,u表示從當(dāng)前地址往后請求顯示的字節(jié)數(shù)
          display 表達(dá)式設(shè)定在單步運行或其他情況中,自動顯示的對應(yīng)表達(dá)式的內(nèi)容
          5.Gdb 中修改運行參數(shù)相關(guān)命令
          Gdb 還可以修改運行時的參數(shù),并使該變量按照用戶當(dāng)前輸入的值繼續(xù)運行。它的設(shè)置方法為:在單步執(zhí)行的過程中,鍵入命令“set 變量=設(shè)定值”。這樣,在此之后,程序就會按照該設(shè)定的值運行了。下面,筆者結(jié)合上一節(jié)的代碼將n的初始值設(shè)為4,其代碼如
          下所示:
          (Gdb) b 7
          Breakpoint 5 at 0x804847a: file test.c, line 7.
          (Gdb) r
          Starting program: /home/yul/test
          The sum of 1-m is 1275
          Breakpoint 5, main () at test.c:7
          7 for(i=1; i<=50; i++)
          (Gdb) set n=4
          (Gdb) c
          Continuing.
          The sum of 1-50 is 1279
          Program exited with code 031.
          可以看到,最后的運行結(jié)果確實比之前的值大了4。
          Gdb的使用切記點:
          · 在Gcc編譯選項中一定要加入“-g”。
          · 只有在代碼處于“運行”或“暫停”狀態(tài)時才能查看變量值。
          · 設(shè)置斷點后程序在指定行之前停
          posted on 2014-01-15 15:59 Eric_jiang 閱讀(386) 評論(2)  編輯  收藏 所屬分類: C 編程

          Feedback

          # re: Gdb 調(diào)試器 2014-01-16 15:25 puyufanyi.com
          http://www.xuexi111.com/book/jisuanji/73042.html  回復(fù)  更多評論
            

          # re: Gdb 調(diào)試器 2014-01-22 14:18 puyufanyi.com
          http://fs.houxue.com/xuexiao-48030/#p=IMAGE78534  回復(fù)  更多評論
            


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
          相關(guān)文章:
           
          主站蜘蛛池模板: 北流市| 三门县| 永德县| 弥渡县| 平阳县| 溧水县| 孝昌县| 呼图壁县| 宁远县| 易门县| 永靖县| 鸡东县| 铅山县| 三门县| 巴南区| 清远市| 乐平市| 新巴尔虎左旗| 剑阁县| 阳山县| 邳州市| 香港 | 巴南区| 湖口县| 大安市| 体育| 三原县| 汝南县| 宜春市| 库尔勒市| 五家渠市| 绵阳市| 深泽县| 临清市| 红桥区| 锡林郭勒盟| 汝州市| 郁南县| 湄潭县| 错那县| 喀什市|