linux下gdb單步調試(上)轉載

來源:互聯網
上載者:User

用 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    <---------- 在斷點處停住。
17               long result = 0;
(gdb) n          <--------------------- 單條語句執行, next 命令簡寫。
18               for(i=1; i<=100; i++)
(gdb) n
20                       result += i;
(gdb) n
18               for(i=1; i<=100; i++)
(gdb) n
20                       result += i;
(gdb) c          <--------------------- 繼續運行程式, continue 命令簡寫。
Continuing.
result[1-100] = 5050       <---------- 程式輸出。

Breakpoint 2, func (n=250) at tst.c:5
5                int sum=0,i;
(gdb) n
6                for(i=1; i<=n; i++)
(gdb) p i        <--------------------- 列印變數 i 的值, print 命令簡寫。
$1 = 134513808
(gdb) n
8                        sum+=i;
(gdb) n
6                for(i=1; i<=n; i++)
(gdb) p sum
$2 = 1
(gdb) n
8                        sum+=i;
(gdb) p i
$3 = 2
(gdb) n
6                for(i=1; i<=n; i++)
(gdb) p sum
$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     <--------------------- 繼續運行。
Continuing.
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 所定義的路徑。

GDB 的命令概貌
———————

啟動 gdb 後,就你被帶入 gdb 的調試環境中,就可以使用 gdb 的命令開始偵錯工具了, gdb 的命令可以使用 help 命令來查看,如下所示:

    /home/hchen> 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) 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
    obscure -- Obscure features
    running -- Running the program
    stack -- Examining the stack
    status -- Status inquiries
    support -- Support facilities
    tracepoints -- Tracing of program execution without stopping the program
    user-defined -- User-defined 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 的命令很多, gdb 把之分成許多個種類。 help 命令只是例出 gdb 的命令種類,如果要看種類中的命令,可以使用 help
<class> 命令,如: help breakpoints ,查看設定斷點的所有命令。也可以直接 help
<command> 來查看命令的協助。

gdb 中,輸入命令時,可以不用打全命令,只用打命令的前幾個字元就可以了,當然,命令的前幾個字元應該要標誌著一個唯一的命令,在 Linux 下,你可以敲擊兩次 TAB 鍵來補齊命令的全稱,如果有重複的,那麼 gdb 會把其例出來。
  
    樣本一:在進入函數 func 時,設定一個斷點。可以敲入 break func ,或是直接就是 b func
    (gdb) b func
    Breakpoint 1 at 0x8048458: file hello.c, line 10.

    樣本二:敲入 b 按兩次 TAB 鍵,你會看到所有 b 打頭的命令:
    (gdb) b
    backtrace break      bt
    (gdb)

    樣本三:只記得函數的首碼,可以這樣:
    (gdb) b make_ < 按 TAB 鍵 >
    (再按下一次 TAB 鍵,你會看到 : )
    make_a_section_from_file     make_environ
    make_abs_section             make_function_type
    make_blockvector             make_pointer_type
    make_cleanup                 make_reference_type
    make_command                 make_symbol_completion_list
    (gdb) b make_
    GDB 把所有 make 開頭的函數全部例出來給你查看。

    樣本四:調試 C++ 的程式時,有可以函數名一樣。如:
    (gdb) b 'bubble( M-?
    bubble(double,double)    bubble(int,int)
    (gdb) b 'bubble(
    你可以查看到 C++ 中的所有的重載函數及參數。(註: M-? 和 “ 按兩次 TAB 鍵 ” 是一個意思)

要退出 gdb 時,只用發 quit 或命令簡稱 q 就行了。

GDB 中運行 UNIX 的 shell 程式
————————————

在 gdb 環境中,你可以執行 UNIX 的 shell 的命令,使用 gdb 的 shell 命令來完成:

    shell <command string>
    調用 UNIX 的 shell 來執行 <command string> ,環境變數 SHELL 中定義的 UNIX 的
shell 將會被用來執行 <command string> ,如果 SHELL 沒有定義,那就使用 UNIX 的標準 shell :
/bin/sh 。(在 Windows 中使用 Command.com 或 cmd.exe )

還有一個 gdb 命令是 make :
    make <make-args>
    可以在 gdb 中執行 make 命令來重新 build 自己的程式。這個命令等價於 “ shell make <make-args> ” 。

在 GDB 中運行程式
————————

當以 gdb <program> 方式啟動 gdb 後, gdb 會在 PATH 路徑和目前的目錄中搜尋 <program> 的源檔案。如要確認 gdb 是否讀到源檔案,可使用 l 或 list 命令,看看 gdb 是否能列出原始碼。

在 gdb 中,運行程式使用 r 或是 run 命令。程式的運行,你有可能需要設定下面四方面的事。

1 、程式運行參數。
    set args 可指定運行時參數。(如: set args 10 20 30 40 50 )
    show args 命令可以查看設定好的運行參數。

2 、運行環境。
    path <dir> 可設定程式的運行路徑。
    show paths 查看程式的運行路徑。
    set environment varname [=value] 設定環境變數。如: set env USER=hchen
    show environment [varname] 查看環境變數。

3 、工作目錄。
    cd <dir> 相當於 shell 的 cd 命令。
    pwd 顯示當前的所在目錄。

4 、程式的輸入輸出。
    info terminal 顯示你程式用到的終端的模式。
    使用重新導向控製程序輸出。如: run > outfile
    tty 命令可以指寫輸入輸出的終端裝置。如: tty /dev/ttyb

調試已啟動並執行程式
————————

兩種方法:
1 、在 UNIX 下用 ps 查看正在啟動並執行程式的 PID (進程 ID ),然後用 gdb <program> PID 格式掛接正在啟動並執行程式。
2 、先用 gdb <program> 關聯上原始碼,並進行 gdb ,在 gdb 中用 attach 命令來掛接進程的 PID 。並用 detach 來取消掛接的進程。

暫停 / 恢複程式運行
—————————

偵錯工具中,暫停程式運行是必須的, GDB 可以方便地暫停程式的運行。你可以設定程式的在哪行停住,在什麼條件下停住,在收到什麼訊號時停往等等。以便於你查看運行時的變數,以及運行時的流程。

當進程被 gdb 停住時,你可以使用 info program 來查看程式的是否在運行,進程號,被暫停原因。

在 gdb 中,我們可以有以下幾種暫停方式:斷點( BreakPoint )、觀察點( WatchPoint )、捕捉點( CatchPoint
)、訊號( Signals )、線程停止( Thread Stops )。如果要恢複程式運行,可以使用 c 或是 continue 命令。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.