1. 程式人生 > >使用gdb除錯當前執行的程式

使用gdb除錯當前執行的程式

用gdb可以除錯當前的程式的使用情況,讀出他的引數。
以下用一個簡單的程式做為例子:來說明gdb的除錯。

第一步  編譯一個死迴圈程式。

/* File name malloc.c*/

#include   <stdio.h>                                                           
#include   <stdlib.h>
#include   <string.h>

void getmem(void **p, int num){
    *p = (void *)malloc(num);
}

void test(void){
    char *str = NULL;
    getmem((void **)&str, 100);
        strcpy(str, "Hello");
    printf("%s/n", str);
}

int main(void){
    int i = 0;
    while(1){
        if (i == 1){
            test();
            return 1;
        }  
    }
    return 0;
}                



我們可以看出,這個程式就是malloc一段記憶體空間,用來供strcpy使用,由於只是除錯一下,就沒有在test程式中加上一些關於strcpy的正確性判斷語句。
函式的正常退出的情況是i==1,但是程式執行過程中根本無法使i==1成立。i的變數的值將會在使用gdb時用到。

開始編譯
$gcc -g malloc.c

得用gdb,加上-g還是需要的。生成的可執行檔案為a.out

第二步  讓gdb連線到正在執行的程序上去
首先執行程式。
$./a.out
明顯的,是一個死迴圈。

重新開一個shell
$ps -u
我的機器的執行情況如下所示:
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
wyc       7712  0.0  0.1   6092  3644 pts/8    Ss   10:24   0:00 bash
wyc       7880  0.0  0.1   6092  3608 pts/9    Ss   10:27   0:00 bash
wyc       7929  0.0  0.3  10848  6468 pts/9    S+   10:28   0:00 gdb
wyc       8347 93.0  0.0   1652   284 pts/8    R+   10:42   0:13 ./a.out
...

看到沒有? ./a.out的程序號是8347。

現在啟動gdb
$gdb


由於是除錯執行的程序,不是可執行檔案,後面不需要跟任何引數。在用 gdb除錯執行狀態下的程式時,最核心的就是gdb內部的attach命令
用法為
 (gdb) attach

這是我的機器上的例子:
$ gdb
GNU gdb (GDB) 7.1.50.20100621
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
For bug reporting instructions, please see:
.
(gdb) attach 8347
Attaching to process 8347
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
main () at malloc.c:19
19            if (i == 1){
(gdb) p i
$1 = 0
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) i=1
Undefined info command: "=1".  Try "help info".
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) set var i=1
(gdb) l
14    }
15   
16    int main(void){
17        int i = 0;
18        while(1){
19            if (i == 1){
20                test();
21                return 1;
22            }
23        }
(gdb) n
20                test();
(gdb)
21                return 1;
(gdb)
25    }
(gdb)
0xb7f47775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb)
Single stepping until exit from function __libc_start_main,
which has no line number information.

Program exited with code 01.
(gdb)

在執行到第20行命令的時候,可以看一下到執行./a.out的那個shell,應該hello字串在標準輸出上了。當gdb中顯示程序退出時,./a.out的shell應該結束了當前程序了。
在gdb中用set var i=1
來修改變數i的值(用set i=1不能識別命令),使程式能夠正常退出。

在除錯時,當前程式呼叫的所有庫也全部都出來了。這個例子中的
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
是a.out程式所呼叫的全部庫。可以用這種辦法分析當前執行的程式的庫的呼叫情況。

千萬不要關掉gdb,以下除錯更精彩:

第三步 在gdb中重啟程式
在上面已經知道了程式正常退出了,但是gdb還沒有退出,這時在gdb中執行run效果如何?

(gdb) run
Starting program: /home/wyc/desktop/my_program/review/a.out
下面是死迴圈了...
接下Ctrl+c,給gdb發個SIGINT的訊號。

^C
Program received signal SIGINT, Interrupt.
main () at malloc.c:19
19            if (i == 1){
(gdb) p i
$2 = 0
(gdb) set var i=1
(gdb) n
20                test();
(gdb) n
Hello
21                return 1;
(gdb) n
25    }
(gdb) n
0xb7e7b775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.

Program exited with code 01.

可以看出,用gdb連線程序後,他會找到執行這個程序所需的全部檔案,當前程序關閉後,仍然可以在gdb中啟動這個程式。

不得不佩服GDB的除錯功能的強大

gdb中的其它命令,就看你分析程式時是否用到了,例如下面的一些簡單的命令:
常用的bt, p , p/x , setp, info registers, break , jump ......