用gdb除錯程式
gdb概述
gdb是gnu開源組織發布的乙個強大的unix下的程式除錯工具。或許,各位比較喜歡那種圖形介面方式的,像vc、bcb等ide的除錯,但如果你是在unix平台下做軟體,你會發現gdb這個除錯工具有比vc、bcb的圖形化偵錯程式更強大的功能。所謂「寸有所長,尺有所短」就是這個道理。
一般來說,gdb主要幫忙你完成下面四個方面的功能:
1、啟動你的程式,可以按照你的自定義的要求隨心所欲的執行程式。
2、可讓被除錯的程式在你所指定的調置的斷點處停住。(斷點可以是條件表示式)
3、當程式被停住時,可以檢查此時你的程式中所發生的事。
4、動態的改變你程式的執行環境。
從上面看來,gdb和一般的除錯工具沒有什麼兩樣,基本上也是完成這些功能,不過在細節上,你會發現gdb這個除錯工具的強大,大家可能比較習慣了圖形化的除錯工具,但有時候,命令列的除錯工具卻有著圖形化工具所不能完成的功能。讓我們一一看來。
用乙個例子告訴你gdb除錯工具如何使用
步驟:(1)在工作目錄上新建檔案greet.c,並用vi啟動:vi great.c
(2)在vi中輸入相應**。(這裡就不具體給出了)
(3)在vi中儲存並推出:使用:wq命令
(4)用gcc編譯:gcc -g greet.c -o greet
(5)執行greet,使用命令./greet,輸出如下結果:
the original string is embedded linux
the original string is
可見,該程式沒有能夠倒序輸出。
(6)啟動gdb除錯:gdb greet
(7)檢視源**,使用命令:l
(8)在30行設定斷點(for迴圈),使用命令:b 30
(9)在33行設定斷點(printf函式),使用命令:b 33
(10)檢視斷點設定情況,使用命令:info b
(11)執行**,使用:r
(12)單步執行**,使用:n
(13)檢視暫停點變數值,使用:p string2[size-i]
(14)繼續單步執行**數次,並檢視string2[size-1]的值是否正確
(15)繼續程式的執行,使用:c
(16)程式在printf函式前停止執行,此時依次檢視string2[0]、string2[1]......,發現string[0]沒有被正確賦值,而後面的賦值都是正確的,這時,定位程式第31行,發現程式執行結果錯誤的原因在於size-1。由於i只能增到size-1,這樣string2[0]就永遠不能被賦值而保持null,故不能輸出任何結果。
(17)退出gdb用:q
(18)重新編譯greet.c,把其中的string2[size-i]=string1[i]改為string2[size-i-1]=string[i]即可。
(19)使用gcc重新編譯:gcc -g greet.c -o greet
(20)產看執行結果:./greet
the original string is embedded linux
the original string is xunil deddebme
這時,輸出正確結果。
另乙個除錯示例
源程式:tst.c
1 #include 2
3 int func(int n)
4 {5 int sum=0,i;
6 for(i=0; i編譯生成執行檔案:(linux下)
hchen/test> cc -g tst.c -o tst
使用gdb除錯:
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也就是你的執行檔案,一般在當然目錄下。
2、gdb core
用gdb同時除錯乙個執行程式和core檔案,core是程式非法執行後core dump後產生的檔案。
3、gdb
如果你的程式是乙個服務程式,那麼你可以指定這個服務程式執行時的程序id。gdb會自動attach上去,並除錯他。program應該在path環境變數中搜尋得到。
gdb啟動時,可以加上一些gdb的啟動開關,詳細的開關可以用gdb -help檢視。我在下面只例舉一些比較常用的引數:
-symbols
-s 從指定檔案中讀取符號表。
-se file
從指定檔案中讀取符號表資訊,並把他用在可執行檔案中。
-core
-c 除錯時core dump的core檔案。
-directory
-d 加入乙個原始檔的搜尋路徑。預設搜尋路徑是環境變數中path所定義的路徑。
用乙個例子說明VBS語法
dim arrcmdline 200 dim ntotalcmdline arrcmdline 1 sdfasdf arrcmdline 2 sdfasdf arrcmdline 3 gettrafile file tf.cpxx.cy1,beg yy mm dd,ter yy mm dd,iv h...
乙個例子讓你理解Generator語法
function foo let generator foo 返回迭代器例項 指標物件 console.log generator.next 111 console.log generator.next aaaa console.log generator.next console.log gene...
介紹乙個node除錯工具 nodemon
這個工具和node supervisor基本上是一致的,但是其功能比較強大,個人覺得在開發環境還是用 nodemon,因為配置比較方便,文件也很清晰。所以這裡先主要講 nodemon。nodemon 的安裝 npm install g nodemon安裝完 nodemon 後,就可以用 nodemo...