㈠ 如何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 ing"
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 ......
㈡ linux入門基礎(四)Gdb調試程序
Gdb調試
注意:在Gcc編譯選項中一定要加入
–g
退出GDB:quit
或
Ctrl+d
調試過程:
1.
查看文件
命令:
(gdb)
l
命令:(gdb)
b
行號
註:到第17行停止,並沒有執行17行
3.
查看斷點情況
info
b
4.
運行代碼
r
命令:
(gdb)
r
(也可以指定行開始運行,在r後面加上行號)
5.
查看變數值
p
命令:(gdb)
p
變數名
6.
設置監視點:
watch
z
(變數名)
也可以是復雜的表達式
7.
單步運行
命令:(gdb)
n
(逐過程)
8.逐步,會進入函數
命令:(gdb)
s
9.條件斷點
將正常斷點轉變為條件斷點:condition
如:condition
1
i
==
10
只有當滿足條件i
==
1時,才會在斷點1處暫停
10.
恢復程序運行
c
命令:
(gdb)
c
(程序就會運行,如果沒有斷點,就運行剩下部分,如果有斷點,就會運行到下一個斷點)
11.
去除斷點
clear
line_number
clear
filename:line_number
12.
help
12.1
help找出類別
12.2help從列表中
㈢ Linux下gdb調試的幾個簡單命令
和在IDE上差不多,無非是單步 繼續 斷點之類的
list列出代碼
run運行
step單步
break斷點
watch查看變數
。。。。
㈣ gcc編譯器可以直接使用gdb命令調試嗎
vs是自帶編譯器跟調試器的。如果你想使用gcc和gdb的話,可以使用code::block這個IDE。他會自己默認自帶gcc編譯器的,他是可以在Windows下使用的
㈤ 如何用GDB進行調試
1: 對於在應用程序中加入參數進行調試的方法:
直接用 gdb app -p1 -p2 這樣進行調試是不行的。
需要像以下這樣使用:
#gdb app
(gdb) r -p1 -p2
或者在運行run命令前使用set args命令:
(gdb) set args p1 p2
可以用show args 命令來查看
2. 加入斷點:
break <linenumber>
break <funcName>
break +offset
break -offset
(在當前行號的前面或後面的offset行停住。)
break filename:linenum
在源文件filename的linenum行處停住。
break filename:function
在源文件filename的function函數的入口處停住。
break ... if
...可以是上述的參數,condition表示條件,在條件成立時停住。比如在循環境體中,可以設置 break if i=100,表示當i為100時停住程序。
3. 查看運行時的堆棧:
使用bt命令
4. 列印某個變數的值:
print val
5. 單步: n
繼續運行:c
step
單步跟蹤,如果有函數調用,他會進入該函數。
next
同樣單步跟蹤,如果有函數調用,他不會進入該函數。很像VC等工具中的step over。後面可以加count也可以不加,不加表示一條條地執行,加表示執行後面的count條指令,然後再停住。
set step-mode
set step-mode on
打開step-mode模式,於是,在進行單步跟蹤時,程序不會因為沒有debug信息而不停住。這個參數有很利於查看機器碼。
set step-mod off
關閉step-mode模式。
finish
運行程序,直到當前函數完成返回。並列印函數返回時的堆棧地址和返回值及參數值等信息。
until 或 u
當你厭倦了在一個循環體內單步跟蹤時,這個命令可以運行程序直到退出循環體。
6.在GDB中執行shell命令:
在gdb環境中,你可以執行UNIX的shell的命令,使用gdb的shell命令來完成:
eg. shell make
7. 運行環境
可設定程序的運行路徑。
show paths 查看程序的運行路徑。
set environment varname [=value] 設置環境變數。如:set env USER=hchen
show environment [varname] 查看環境變數。
8.觀察點(WatchPoint)
觀察點一般來觀察某個表達式(變數也是一種表達式)的值是否有變化了,如果有變化,馬上停住程 序。我們有下面的幾種方法來設置觀察點:
watch
為表達式(變數)expr設置一個觀察點。一量表達式值有變化時,馬上停住程序。
rwatch
當表達式(變數)expr被讀時,停住程序。
awatch
當表達式(變數)的值被讀或被寫時,停住程序。
info watchpoints
列出當前所設置了的所有觀察點。
9. 維護breakpoint
clear
清除所有的已定義的停止點。
clear func
清除所有設置在函數上的停止點。
delete [breakpoints] [range...]
刪除指定的斷點,breakpoints為斷點號。如果不指定斷點號,則表示刪除所有的斷點。range 表示斷點號的范圍(如:3-7)。其簡寫命令為d。
比刪除更好的一種方法是disable停止點,disable了的停止點,GDB不會刪除,當你還需要時,enable即可,就好像回收站一樣。
disable [breakpoints] [range...]
disable所指定的停止點,breakpoints為停止點號。如果什麼都不指定,表示disable所有的停止 點。簡寫命令是dis.
enable [breakpoints] [range...]
enable所指定的停止點,breakpoints為停止點號。
10、程序變數
查看文件中某變數的值:
file::variable
function::variable
可以通過這種形式指定你所想查看的變數,是哪個文件中的或是哪個函數中的。例如,查看文件f2.c中的全局變數x的值:
gdb) p 'f2.c'::x
查看數組的值
有時候,你需要查看一段連續的內存空間的值。比如數組的一段,或是動態分配的數據的大小。你可以使用GDB的「@」操作符,「@」的左邊是第一個內存的地址的值,「@」的右邊則你你想查看內存的長度。例如,你的程序中有這樣的語句:
int *array = (int *) malloc (len * sizeof (int));
於是,在GDB調試過程中,你可以以如下命令顯示出這個動態數組的取值:
p *array@len
如果是靜態數組的話,可以直接用print數組名,就可以顯示數組中所有數據的內容了。
11.輸出格式
一般來說,GDB會根據變數的類型輸出變數的值。但你也可以自定義GDB的輸出的格式。例如,你想輸出一個整數的十六進制,或是二進制來查看這個整型變數的中的位的情況。要做到這樣,你可以使用GDB的數據顯示格式:
x 按十六進制格式顯示變數。
d 按十進制格式顯示變數。
u 按十六進制格式顯示無符號整型。
o 按八進制格式顯示變數。
t 按二進制格式顯示變數。
a 按十六進制格式顯示變數。
c 按字元格式顯示變數。
f 按浮點數格式顯示變數。
(gdb) p i
$21 = 101
(gdb) p/a i
$22 = 0x65
(gdb) p/c i
$23 = 101 'e'
(gdb) p/f i
$24 = 1.41531145e-43
(gdb) p/x i
$25 = 0x65
(gdb) p/t i
$26 = 1100101
11.查看內存
使用examine命令(簡寫是x)來查看內存地址中的值。x命令的語法如下所示:
x/
n、f、u是可選的參數。
n 是一個正整數,表示顯示內存的長度,也就是說從當前地址向後顯示幾個地址的內容。
f 表示顯示的格式,參見上面。如果地址所指的是字元串,那麼格式可以是s,如果地十是指令地址,那麼格式可以是i。
u 表示從當前地址往後請求的位元組數,如果不指定的話,GDB默認是4個bytes。u參數可以用下面的字元來代替,b表示單位元組,h表示雙位元組,w表示四位元組,g表示八位元組。當我們指定了位元組長度後,GDB會從指內存定的內存地址開始,讀寫指定位元組,並把其當作一個值取出來。
n/f/u三個參數可以一起使用。例如:
命令:x/3uh 0x54320 表示,從內存地址0x54320讀取內容,h表示以雙位元組為一個單位,3表示三個單位,u表示按十六進制顯示。
12.自動顯示
你可以設置一些自動顯示的變數,當程序停住時,或是在你單步跟蹤時,這些變數會自動顯示。相關的GDB命令是display。
display
display/
display/ expr
expr是一個表達式,fmt表示顯示的格式,addr表示內存地址,當你用display設定好了一個或多個表達式後,只要你的程序被停下來,GDB會自動顯示你所設置的這些表達式的值。
格式i和s同樣被display支持,一個非常有用的命令是:
display/i $pc
undisplay
delete display
刪除自動顯示,dnums意為所設置好了的自動顯式的編號。
disable display
enable display
disable和enalbe不刪除自動顯示的設置,而只是讓其失效和恢復。
info display
查看display設置的自動顯示的信息。GDB會打出一張表格,向你報告當然調試中設置了多少個自動顯示設置,其中包括,設置的編號,表達式,是否enable。
13. 設置顯示選項
set print address
set print address on
打開地址輸出,當程序顯示函數信息時,GDB會顯出函數的參數地址。系統默認為打開的,
show print address
查看當前地址顯示選項是否打開。
set print array
set print array on
打開數組顯示,打開後當數組顯示時,每個元素佔一行,如果不打開的話,每個元素則以逗號分隔。這個選項默認是關閉的。與之相關的兩個命令如下,我就不再多說了。
set print array off
show print array
set print elements
這個選項主要是設置數組的,如果你的數組太大了,那麼就可以指定一個來指定數據顯示的最大長度,當到達這個長度時,GDB就不再往下顯示了。如果設置為0,則表示不限制。
show print elements
查看print elements的選項信息。
set print null-stop
如果打開了這個選項,那麼當顯示字元串時,遇到結束符則停止顯示。這個選項默認為off。
set print pretty on
如果打開printf pretty這個選項,那麼當GDB顯示結構體時會比較漂亮。
14.關於顯示源碼list
㈥ 一本關於GDB調試的書籍,書中詳細的介紹了,如何在LINUX中使用GDB及其命令!-It is a book abo
.rar] -gdb相關資料,整理的真的很辛苦,希望大家好好珍惜[gdb調試工具指南.rar] -gdb調試工具指南[PrintBar_src.zip ] - 關於列印票據的源代碼,支持固定行數的分頁[centermanifold06.rar ] - 該程序用來處理微分方程系統的,用來化簡一個微分系統的[gdb .rar] - 一本介紹gdb調試的書籍,想要深入學習在linux下編程的朋友們可以看下[gdb
㈦ gdb 的 l 命令
gcc test.c -o test -g
那個-g是告訴gcc把調試信息加進來的。 具體你可以man gcc看看。
-g:
Proce debugging information in the operating system's native format. GDB can work with this debugging information.
㈧ 我下載了一個gdb調試器,然後我在命令行調試程序,它說gdb不內部或外部命令,也不是可運行的程序或批處理
win下把 gdb 全部放到 c:\windows\system32 下面
在cmd下啟動 gdb。
或者 你把 gdb 解壓到某個文件夾比如: d:\gdb
然後在系統環境變數里設置 PATH 變數,在裡面添加 d:\gdb 就可以了。路徑之間用分號隔開。
然後你啟動一個cmd 就可以運行gdb了。
我把修改PATH 的資料發到你消息裡面。
㈨ 如何在Windows的命令行下進行程序編譯和gdb調試
1、概念介紹。
1、Windows下的cmd就是Windows的命令行終端,其中的一些命令和Ubuntu的有些許區別,不過在這個博客的范疇中沒有涉及。
2、Windows的環境變數,大概可以說是如果設置好了在path路徑裡面了,就可以直接在cmd命令行里直接調用程序。
2、配置操作
1、選擇計算機,右鍵,選擇「屬性」
2、「高級系統設置」 –> 「環境變數」
3、選擇「環境變數」裡面的「系統變數」 ,選擇path, 編輯
4、添加環境變數。注意:最好不要動原來的東西,在原來的東西的基礎上在前面或後面加上一個分號,然後把Dev C++安裝目錄下的MinGW64/bin文件夾的路徑復制到環境變數裡面去。。(此處是巧借了dev的自帶編譯器,如果各位以其他方法找到了新版的MinGW文件的話,也可以配置成自己喜歡的)注意,路徑中不要出現中文,否則可能出現有趣的問題
(ps:博主這邊用的就不是dev 的MinGW64包了,而是師兄傳下來的 :))
4、一路確定,配置完成。
3、使用操作
在你代碼所在的文件夾,按住shift加右鍵,點擊「在此處打開命令窗口」,進入到cmd終端,接下來就可以愉快地使用g++,gcc編譯器,和gdb調試器了。
4、後期優化
大家還可以給自己配一個用的順手的編輯器,比如sublime,gvim,(甚至是notepad ,hhh)同理把它放在環境變數里,那麼也可以在cmd中直接打開,這時在win下的編程過程就和Ubuntu的非常像了。。
5、備注
1、此處以win7為例,其他版本的應該大同小異。
2、另附片面的gdb調試方法
3、使用編輯器和命令行編譯的方法對於了解程序的運行過程更加有好處,但是從方便性上的確不如IDE,特別是用熟了vs的同學們就應該更能體會得到,所以各有利弊,大家自己選擇最符合自己口味的編程環境就好:)
㈩ 請指出gdb調試中命令"n"和"s"的區別
set 功能較多,簡易修改變數時總加上var (gdb) p n $1 = 0 (gdb) set n=5 "on" or "off" expected. (gdb) set var n=5 (gdb) p n $2 = 5