天天看點

用GDB調試程式(一)

GDB概述

————

GDB是GNU開源組織釋出的一個強大的UNIX下的程式調試工具。或許,各位比較喜歡那種圖形界面方式的,像VC、BCB等IDE的調試,但如果你是在UNIX平台下做軟體,你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。

一般來說,GDB主要幫忙你完成下面四個方面的功能:

    1、啟動你的程式,可以按照你的自定義的要求随心所欲的運作程式。

    2、可讓被調試的程式在你所指定的調置的斷點處停住。(斷點可以是條件表達式)

    3、當程式被停住時,可以檢查此時你的程式中所發生的事。

    4、動态的改變你程式的執行環境。

從上面看來,GDB和一般的調試工具沒有什麼兩樣,基本上也是完成這些功能,不過在細節上,你會發現GDB這個調試工具的強大,大家可能比較習慣了圖形化的調試工具,但有時候,指令行的調試工具卻有着圖形化工具所不能完成的功能。讓我們一一看來。

一個調試示例

——————

源程式:tst.c

     1 #include <stdio.h>

     2

     3 int func(int n)

     4 {

     5         int sum=0,i;

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

     7         {

     8                 sum+=i;

     9         }

    10         return sum;

    11 }

    12

    13

    14 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] = %d /n", result );

    24        printf("result[1-250] = %d /n", func(250) );

    25 }

編譯生成執行檔案:(Linux下)

    hchen/test> cc -g tst.c -o tst

使用GDB調試:

hchen/test> gdb tst  <---------- 啟動GDB

GNU gdb 5.1.1

Copyright 2002 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-suse-linux"...

(gdb) l     <-------------------- l指令相當于list,從第一行開始例出原碼。

1        #include <stdio.h>

2

3        int func(int n)

4        {

5                int sum=0,i;

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

7                {

8                        sum+=i;

9                }

10               return sum;

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

11       }

12

13

14       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 0x8048496: file tst.c, line 16.

(gdb) break func  <-------------------- 設定斷點,在函數func()入口處。

Breakpoint 2 at 0x8048456: file tst.c, line 5.

(gdb) info break  <-------------------- 檢視斷點資訊。

Num Type           Disp Enb Address    What

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

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

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

Starting program: /home/hchen/test/tst

Breakpoint 1, main () at tst.c:17    <---------- 在斷點處停住。

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

(gdb) n

20                       result += i;

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

Continuing.

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

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

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

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

$1 = 134513808

(gdb) p sum

$2 = 1

(gdb) p i

$3 = 2

$4 = 3

(gdb) bt        <--------------------- 檢視函數堆棧。

#0  func (n=250) at tst.c:5

#1  0x080484e4 in main () at tst.c:24

#2  0x400409ed in __libc_start_main () from /lib/libc.so.6

(gdb) finish    <--------------------- 退出函數。

Run till exit from #0  func (n=250) at tst.c:5

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

24              printf("result[1-250] = %d /n", func(250) );

Value returned is $6 = 31375

(gdb) c     <--------------------- 繼續運作。

result[1-250] = 31375    <----------程式輸出。

Program exited with code 027. <--------程式退出,調試結束。

(gdb) q     <--------------------- 退出gdb。

hchen/test>

好了,有了以上的感性認識,還是讓我們來系統地認識一下gdb吧。

使用GDB

一般來說GDB主要調試的是C/C++的程式。要調試C/C++的程式,首先在編譯時,我們必須要把調試資訊加到可執行檔案中。使用編譯器(cc/gcc/g++)的 -g 參數可以做到這一點。如:

    > cc -g hello.c -o hello

    > g++ -g hello.cpp -o hello

如果沒有-g,你将看不見程式的函數名、變量名,所代替的全是運作時的記憶體位址。當你用-g把調試資訊加入之後,并成功編譯目标代碼以後,讓我們來看看如何用gdb來調試他。

啟動GDB的方法有以下幾種:

    1、gdb <program> 

       program也就是你的執行檔案,一般在當然目錄下。

    2、gdb <program> core

       用gdb同時調試一個運作程式和core檔案,core是程式非法執行後core dump後産生的檔案。

    3、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所定義的路徑。